diff --git a/DEPS b/DEPS
index 859d74e6..e596376d 100644
--- a/DEPS
+++ b/DEPS
@@ -228,7 +228,7 @@
   # 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': 'b43596f10be4ddd8a607015dd201f580081a008f',
+  'skia_revision': '14a9b089b6bf119e207b827700c4f20bac97b2ed',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -240,7 +240,7 @@
   # 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': 'b7de6caa43b9d92266603071cc28a7dd50850360',
+  'swiftshader_revision': 'e6cfc086849ab23e0e848d291b87a892d63557c6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -295,7 +295,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': '2c91d8f11cf564e4bbff8a401244b2326a600907',
+  'catapult_revision': 'fb6990454da9ed24ad473803c53a04173ba0f948',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -327,7 +327,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_platform-tools_version
   # and whatever else without interference from each other.
-  'android_sdk_platform-tools_version': 'qi_k82nm6j9nz4dQosOoqXew4_TFAy8rcGOHDLptx1sC',
+  'android_sdk_platform-tools_version': 'g7n_-r6yJd_SGRklujGB1wEt8iyr77FZTUJVS9w6O34C',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_platforms_version
   # and whatever else without interference from each other.
@@ -872,7 +872,7 @@
           },
           {
               'package': 'chromium/third_party/android_sdk/public/cmdline-tools',
-              'version': 'ZT3JmI6GMG4YVcZ1OtECRVMOLLJAWAdPbi-OclubJLMC',
+              'version': 'yODElY4RdHopNEfpOnqjRcrpa6JMzbhYYqGD53-DjJwC',
           },
       ],
       'condition': 'checkout_android_native_support',
@@ -962,6 +962,9 @@
       'dep_type': 'cipd',
   },
 
+  'src/third_party/cast_core/public/src':
+    Var('chromium_git') + '/cast_core/public' + '@' + '3ca33709a8b745f1e2492fba3aa969d9cef70029',
+
   'src/third_party/catapult':
     Var('chromium_git') + '/catapult.git' + '@' + Var('catapult_revision'),
 
@@ -989,7 +992,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '8d0b9b07caf9eeec4921feb0854281e4ed7837bf',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'b7e5ac97be8b399c3d854db0942136a53c7d3086',
       'condition': 'checkout_chromeos',
   },
 
@@ -1009,7 +1012,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'cf9d64363b627bc156be3166aed94affb5cae6b1',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'eb28118b7a61ec5c21906b6fceea657d66b4f004',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1674,7 +1677,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bba34257682fc7f9cd422709d2ef1d4f5c23ac4f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@4abb7127fda147ecff791ba96b59481b0857ca3c',
     'condition': 'checkout_src_internal',
   },
 
@@ -1693,7 +1696,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'zBfE9yyjhvbsHqoz8Kw2gS_uedqEZ9gAPeYdLKJkFOkC',
+        'version': 'fX0HZw_FTBqjH2nIbFWs6am1yxOzBjztaj2FDTXnEDMC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 3cbf6d4..c85026e 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -1476,6 +1476,51 @@
           '\n'.join(problems))
   ]
 
+def CheckForgettingMAYBEInTests(input_api, output_api):
+  """Checks to make sure tests disabled conditionally are not missing a
+  corresponding MAYBE_ prefix.
+  """
+  # Expect at least a lowercase character in the test name. This helps rule out
+  # false positives with macros wrapping the actual tests name.
+  define_maybe_pattern = input_api.re.compile(
+      r'^\#define MAYBE_(?P<test_name>\w*[a-z]\w*)')
+  test_maybe_pattern = r'^\s*\w*TEST[^(]*\(\s*\w+,\s*MAYBE_{test_name}\)'
+  suite_maybe_pattern = r'^\s*\w*TEST[^(]*\(\s*MAYBE_{test_name}[\),]'
+  warnings = []
+
+  # Read the entire files. We can't just read the affected lines, forgetting to
+  # add MAYBE_ on a change would not show up otherwise.
+  for f in input_api.AffectedFiles(False):
+    if not 'test' in f.LocalPath() or not f.LocalPath().endswith('.cc'):
+      continue
+    contents = input_api.ReadFile(f)
+    lines = contents.splitlines(True)
+    current_position = 0
+    warning_test_names = set()
+    for line_num, line in enumerate(lines, start=1):
+      current_position += len(line)
+      maybe_match = define_maybe_pattern.search(line)
+      if maybe_match:
+        test_name = maybe_match.group('test_name')
+        # Do not warn twice for the same test.
+        if (test_name in warning_test_names):
+          continue
+        warning_test_names.add(test_name)
+
+        # Attempt to find the corresponding MAYBE_ test or suite, starting from
+        # the current position.
+        test_match = input_api.re.compile(
+            test_maybe_pattern.format(test_name=test_name),
+            input_api.re.MULTILINE).search(contents, current_position)
+        suite_match = input_api.re.compile(
+            suite_maybe_pattern.format(test_name=test_name),
+            input_api.re.MULTILINE).search(contents, current_position)
+        if not test_match and not suite_match:
+          warnings.append(
+              output_api.PresubmitPromptWarning(
+                '%s:%d found MAYBE_ defined without corresponding test %s' %
+                (f.LocalPath(), line_num, test_name)))
+  return warnings
 
 def CheckDCHECK_IS_ONHasBraces(input_api, output_api):
   """Checks to make sure DCHECK_IS_ON() does not skip the parentheses."""
diff --git a/PRESUBMIT_test.py b/PRESUBMIT_test.py
index cc9d6ad..122bf2e 100755
--- a/PRESUBMIT_test.py
+++ b/PRESUBMIT_test.py
@@ -3415,6 +3415,101 @@
                                                    MockOutputApi())
     self.assertEqual(0, len(results))
 
+class ForgettingMAYBEInTests(unittest.TestCase):
+  def testPositive(self):
+    test = (
+        '#if defined(HAS_ENERGY)\n'
+        '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
+        '#else\n'
+        '#define MAYBE_CastExplosion CastExplosion\n'
+        '#endif\n'
+        'TEST_F(ArchWizard, CastExplosion) {\n'
+        '#if defined(ARCH_PRIEST_IN_PARTY)\n'
+        '#define MAYBE_ArchPriest ArchPriest\n'
+        '#else\n'
+        '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
+        '#endif\n'
+        'TEST_F(ArchPriest, CastNaturesBounty) {\n'
+        '#if !defined(CRUSADER_IN_PARTY)\n'
+        '#define MAYBE_Crusader \\\n'
+        '    DISABLED_Crusader \n'
+        '#else\n'
+        '#define MAYBE_Crusader \\\n'
+        '    Crusader\n'
+        '#endif\n'
+        '  TEST_F(\n'
+        '    Crusader,\n'
+        '    CastTaunt) { }\n'
+        '#if defined(LEARNED_BASIC_SKILLS)\n'
+        '#define MAYBE_CastSteal \\\n'
+        '    DISABLED_CastSteal \n'
+        '#else\n'
+        '#define MAYBE_CastSteal \\\n'
+        '    CastSteal\n'
+        '#endif\n'
+        '  TEST_F(\n'
+        '    ThiefClass,\n'
+        '    CastSteal) { }\n'
+    )
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+        MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
+    ]
+    results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
+                                                    MockOutputApi())
+    self.assertEqual(4, len(results))
+    self.assertTrue('CastExplosion' in results[0].message)
+    self.assertTrue('fantasyworld/classes_unittest.cc:2' in results[0].message)
+    self.assertTrue('ArchPriest' in results[1].message)
+    self.assertTrue('fantasyworld/classes_unittest.cc:8' in results[1].message)
+    self.assertTrue('Crusader' in results[2].message)
+    self.assertTrue('fantasyworld/classes_unittest.cc:14' in results[2].message)
+    self.assertTrue('CastSteal' in results[3].message)
+    self.assertTrue('fantasyworld/classes_unittest.cc:24' in results[3].message)
+
+  def testNegative(self):
+    test = (
+        '#if defined(HAS_ENERGY)\n'
+        '#define MAYBE_CastExplosion DISABLED_CastExplosion\n'
+        '#else\n'
+        '#define MAYBE_CastExplosion CastExplosion\n'
+        '#endif\n'
+        'TEST_F(ArchWizard, MAYBE_CastExplosion) {\n'
+        '#if defined(ARCH_PRIEST_IN_PARTY)\n'
+        '#define MAYBE_ArchPriest ArchPriest\n'
+        '#else\n'
+        '#define MAYBE_ArchPriest DISABLED_ArchPriest\n'
+        '#endif\n'
+        'TEST_F(MAYBE_ArchPriest, CastNaturesBounty) {\n'
+        '#if !defined(CRUSADER_IN_PARTY)\n'
+        '#define MAYBE_Crusader \\\n'
+        '    DISABLED_Crusader \n'
+        '#else\n'
+        '#define MAYBE_Crusader \\\n'
+        '    Crusader\n'
+        '#endif\n'
+        '  TEST_F(\n'
+        '    MAYBE_Crusader,\n'
+        '    CastTaunt) { }\n'
+        '#if defined(LEARNED_BASIC_SKILLS)\n'
+        '#define MAYBE_CastSteal \\\n'
+        '    DISABLED_CastSteal \n'
+        '#else\n'
+        '#define MAYBE_CastSteal \\\n'
+        '    CastSteal\n'
+        '#endif\n'
+        '  TEST_F(\n'
+        '    ThiefClass,\n'
+        '    MAYBE_CastSteal) { }\n'
+    )
+
+    mock_input_api = MockInputApi()
+    mock_input_api.files = [
+        MockFile('fantasyworld/classes_unittest.cc', test.splitlines()),
+    ]
+    results = PRESUBMIT.CheckForgettingMAYBEInTests(mock_input_api,
+                                                    MockOutputApi())
+    self.assertEqual(0, len(results))
 
 class CheckFuzzTargetsTest(unittest.TestCase):
 
diff --git a/ash/DEPS b/ash/DEPS
index e186a36b..ba36485 100644
--- a/ash/DEPS
+++ b/ash/DEPS
@@ -14,12 +14,10 @@
   "+components/prefs",
   "+components/quirks",
   "+components/services/app_service/public",
-  "+components/session_manager",
   "+components/soda",
   "+components/strings",
   "+components/sync",
   "+components/ui_devtools",
-  "+components/user_manager",
   "+components/vector_icons",
   "+components/viz/common",
   "+components/viz/host",
@@ -87,10 +85,21 @@
   "+chromeos/ui",
 
   # ui/base/idle depends on SessionManagerClient so disallow it.
-  "-ui/base/idle"
+  "-ui/base/idle",
 
-  # InputMethodManager lives in the browser process. Use ImeController.
-  "-ui/base/ime/ash/input_method_manager.h"
+  # user_manager::UserManager and session_manager::SessionManager lives in the
+  # browser process. Use SessionController to access user or user session info
+  # so that ash code depends on a single source of truth. If the info is not
+  # available, add new interface to SessionControllerClient and friends to
+  # bridge data from user_manager::UserManager or
+  # session_manager::SessionManager.
+  "-components/session_manager",
+  "+components/session_manager/session_manager_types.h",
+  "-components/user_manager",
+  "+components/user_manager/known_user.h",
+  "+components/user_manager/user_names.h",
+  "+components/user_manager/user_type.h",
+  "+components/user_manager/user.h",
 ]
 
 specific_include_rules = {
@@ -109,7 +118,4 @@
   "window_manager.cc": [
     "+ash/host/ash_window_tree_host.h"
   ],
-  "window_service_delegate_impl.cc": [
-    "+ash/host/ash_window_tree_host.h"
-  ],
 }
diff --git a/ash/accelerometer/accelerometer_samples_observer.cc b/ash/accelerometer/accelerometer_samples_observer.cc
index aeb4f0b..1a91043 100644
--- a/ash/accelerometer/accelerometer_samples_observer.cc
+++ b/ash/accelerometer/accelerometer_samples_observer.cc
@@ -221,8 +221,8 @@
 
   LOG(ERROR) << "OnObserverDisconnect error, assuming IIO Service crashes and "
                 "waiting for its relaunch.";
-  // Don't reset |sensor_device_remote_| so that LightProviderMojo can get the
-  // disconnection.
+  // Don't reset |sensor_device_remote_| so that AccelerometerProviderMojo can
+  // get the disconnection.
   receiver_.reset();
 }
 
diff --git a/ash/ambient/backdrop/DEPS b/ash/ambient/backdrop/DEPS
new file mode 100644
index 0000000..dd73a6b
--- /dev/null
+++ b/ash/ambient/backdrop/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+  # TODO(crbug/1251346): Remove.
+  "ambient_backend_controller_impl.cc": [
+    "+components/user_manager/user_manager.h",
+  ],
+}
diff --git a/ash/frame_throttler/frame_throttling_controller.cc b/ash/frame_throttler/frame_throttling_controller.cc
index 1d1fee1..1715745 100644
--- a/ash/frame_throttler/frame_throttling_controller.cc
+++ b/ash/frame_throttler/frame_throttling_controller.cc
@@ -202,4 +202,9 @@
   arc_observers_.RemoveObserver(observer);
 }
 
+bool FrameThrottlingController::HasArcObserver(
+    FrameThrottlingObserver* observer) {
+  return arc_observers_.HasObserver(observer);
+}
+
 }  // namespace ash
diff --git a/ash/frame_throttler/frame_throttling_controller.h b/ash/frame_throttler/frame_throttling_controller.h
index e68eff0..fa77a3f 100644
--- a/ash/frame_throttler/frame_throttling_controller.h
+++ b/ash/frame_throttler/frame_throttling_controller.h
@@ -61,6 +61,7 @@
 
   void AddArcObserver(FrameThrottlingObserver* observer);
   void RemoveArcObserver(FrameThrottlingObserver* observer);
+  bool HasArcObserver(FrameThrottlingObserver* observer);
 
   uint8_t throttled_fps() const { return throttled_fps_; }
 
diff --git a/ash/quick_pair/feature_status_tracker/DEPS b/ash/quick_pair/feature_status_tracker/DEPS
new file mode 100644
index 0000000..644f774
--- /dev/null
+++ b/ash/quick_pair/feature_status_tracker/DEPS
@@ -0,0 +1,9 @@
+specific_include_rules = {
+  # TODO(crbug/1251346): Remove.
+  "fast_pair_enabled_provider_unittest.cc": [
+    "+components/user_manager",
+  ],
+  "logged_in_user_enabled_provider.h": [
+    "+components/user_manager/user_manager.h",
+  ],
+}
diff --git a/ash/resources/vector_icons/send.icon b/ash/resources/vector_icons/send.icon
index 43c2e65..3e5e313b 100644
--- a/ash/resources/vector_icons/send.icon
+++ b/ash/resources/vector_icons/send.icon
@@ -1,12 +1,18 @@
-// Copyright 2018 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.
 
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 2.01f, 21,
-LINE_TO, 23, 12,
-LINE_TO, 2.01f, 3,
-LINE_TO, 2, 10,
-R_LINE_TO, 15, 2,
-R_LINE_TO, -15, 2,
+CANVAS_DIMENSIONS, 20,
+MOVE_TO, 3, 3,
+LINE_TO, 18, 10,
+LINE_TO, 3, 17,
+V_LINE_TO, 3,
+CLOSE,
+MOVE_TO, 4.5f, 5.36f,
+LINE_TO, 14.45f, 10,
+LINE_TO, 4.5f, 14.64f,
+V_LINE_TO, 12,
+LINE_TO, 9, 10,
+LINE_TO, 4.5f, 8,
+V_LINE_TO, 5.36f,
 CLOSE
diff --git a/ash/system/message_center/ash_notification_input_container.cc b/ash/system/message_center/ash_notification_input_container.cc
index 335b70d..297169c3 100644
--- a/ash/system/message_center/ash_notification_input_container.cc
+++ b/ash/system/message_center/ash_notification_input_container.cc
@@ -9,7 +9,6 @@
 #include "ash/style/ash_color_provider.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/gfx/rrect_f.h"
-#include "ui/message_center/vector_icons.h"
 #include "ui/views/background.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/highlight_path_generator.h"
@@ -23,15 +22,19 @@
 // ImageButton.
 constexpr int kBetweenChildSpacing = 12;
 
-// The icon size of inline reply input field.
-constexpr int kInputReplyButtonSize = 20;
-
-// Padding of the textfield, inside the rounded background.
-constexpr gfx::Insets kInputTextfieldPaddingCrOS(6, 12, 6, 12);
-
 // Insets for inside the border.
 constexpr gfx::Insets kInsideBorderInsets(6, 16, 14, 16);
 
+// The icon size of inline reply input field.
+constexpr int kInputReplyButtonSize = 20;
+// Padding on the input reply button.
+constexpr gfx::Insets kInputReplyButtonPadding(0, 6, 0, 6);
+// Radius of the circular input reply button highlight.
+constexpr int kInputReplyHighlightRadius =
+    (kInputReplyButtonPadding.width() + kInputReplyButtonSize) / 2;
+
+// Padding of the textfield, inside the rounded background.
+constexpr gfx::Insets kInputTextfieldPaddingCrOS(6, 12, 6, 12);
 // Corner radius of the grey background of the textfield.
 constexpr int kTextfieldBackgroundCornerRadius = 24;
 
@@ -57,6 +60,28 @@
   const views::Textfield* const textfield_;
 };
 
+// Inline reply's send button's highlight path generator. Draws a circular
+// highlight path.
+class SendButtonHighlightPathGenerator : public views::HighlightPathGenerator {
+ public:
+  explicit SendButtonHighlightPathGenerator(views::ImageButton* button)
+      : button_(button) {}
+  SendButtonHighlightPathGenerator(const SendButtonHighlightPathGenerator&) =
+      delete;
+  SendButtonHighlightPathGenerator& operator=(
+      const SendButtonHighlightPathGenerator&) = delete;
+
+  // views::HighlightPathGenerator:
+  absl::optional<gfx::RRectF> GetRoundRect(const gfx::RectF& rect) override {
+    return gfx::RRectF(gfx::RectF(button_->GetLocalBounds()),
+                       kInputReplyHighlightRadius);
+  }
+
+ private:
+  // Owned by the views hierarchy.
+  const views::ImageButton* const button_;
+};
+
 }  // namespace
 
 AshNotificationInputContainer::AshNotificationInputContainer(
@@ -94,18 +119,25 @@
       std::make_unique<TextfieldHighlightPathGenerator>(textfield()));
 }
 
+gfx::Insets AshNotificationInputContainer::GetSendButtonPadding() const {
+  return kInputReplyButtonPadding;
+}
+
+void AshNotificationInputContainer::SetSendButtonHighlightPath() {
+  views::HighlightPathGenerator::Install(
+      button(), std::make_unique<SendButtonHighlightPathGenerator>(button()));
+}
+
 void AshNotificationInputContainer::UpdateButtonImage() {
   if (!GetWidget())
     return;
 
-  // TODO(crbug/1249259): Replace this icon with the new icon once UX delivers
-  // it.
   button()->SetImage(
       views::Button::STATE_NORMAL,
-      gfx::CreateVectorIcon(
-          message_center::kNotificationInlineReplyIcon, kInputReplyButtonSize,
-          ash::AshColorProvider::Get()->GetContentLayerColor(
-              ash::AshColorProvider::ContentLayerType::kButtonIconColor)));
+      gfx::CreateVectorIcon(kSendIcon, kInputReplyButtonSize,
+                            ash::AshColorProvider::Get()->GetControlsLayerColor(
+                                ash::AshColorProvider::ControlsLayerType::
+                                    kControlBackgroundColorActive)));
 }
 
 }  // namespace ash
diff --git a/ash/system/message_center/ash_notification_input_container.h b/ash/system/message_center/ash_notification_input_container.h
index 75d98b1..f16b3a4 100644
--- a/ash/system/message_center/ash_notification_input_container.h
+++ b/ash/system/message_center/ash_notification_input_container.h
@@ -29,6 +29,8 @@
   views::InkDropContainerView* InstallInkDrop() override;
   gfx::Insets GetTextfieldPadding() const override;
   void SetTextfieldBackground() override;
+  gfx::Insets GetSendButtonPadding() const override;
+  void SetSendButtonHighlightPath() override;
   void UpdateButtonImage() override;
 };
 
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc
index 7b458965..e69647f 100644
--- a/ash/system/time/calendar_view.cc
+++ b/ash/system/time/calendar_view.cc
@@ -67,6 +67,7 @@
  public:
   explicit CalendarLabel(const std::u16string& text) : views::Label(text) {
     views::Label::SetEnabledColor(calendar_utils::GetPrimaryTextColor());
+    views::Label::SetAutoColorReadabilityEnabled(false);
   }
   CalendarLabel(const CalendarLabel&) = delete;
   CalendarLabel& operator=(const CalendarLabel&) = delete;
@@ -111,6 +112,77 @@
 
 }  // namespace
 
+// The label for each month.
+class CalendarView::MonthYearHeaderView : public views::View {
+ public:
+  MonthYearHeaderView(LabelType type,
+                      CalendarViewController* calendar_view_controller)
+      : month_label_(AddChildView(std::make_unique<views::Label>())) {
+    switch (type) {
+      case PREVIOUS:
+        date_ = calendar_view_controller->GetPreviousMonthFirstDay();
+        month_name_ = calendar_view_controller->GetPreviousMonthName();
+        break;
+      case CURRENT:
+        date_ = calendar_view_controller->GetOnScreenMonthFirstDay();
+        month_name_ = calendar_view_controller->GetOnScreenMonthName();
+        break;
+      case NEXT:
+        date_ = calendar_view_controller->GetNextMonthFirstDay();
+        month_name_ = calendar_view_controller->GetNextMonthName();
+        break;
+    }
+    SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::Orientation::kHorizontal));
+
+    month_label_->SetText(month_name_);
+    SetupLabel(month_label_);
+    month_label_->SetBorder(
+        views::CreateEmptyBorder(gfx::Insets(kLabelVerticalPadding, 0)));
+
+    if (calendar_utils::GetExploded(date_).year !=
+        calendar_utils::GetExploded(base::Time::Now()).year) {
+      year_label_ = AddChildView(std::make_unique<views::Label>());
+      year_label_->SetText(base::UTF8ToUTF16(
+          base::NumberToString(calendar_utils::GetExploded(date_).year)));
+      SetupLabel(year_label_);
+      year_label_->SetBorder(views::CreateEmptyBorder(
+          gfx::Insets(kLabelVerticalPadding, kLabelTextInBetweenPadding)));
+    }
+  }
+  MonthYearHeaderView(const MonthYearHeaderView&) = delete;
+  MonthYearHeaderView& operator=(const MonthYearHeaderView&) = delete;
+  ~MonthYearHeaderView() override = default;
+
+  // views::View:
+  void OnThemeChanged() override {
+    views::View::OnThemeChanged();
+
+    month_label_->SetEnabledColor(calendar_utils::GetPrimaryTextColor());
+    if (year_label_)
+      year_label_->SetEnabledColor(calendar_utils::GetSecondaryTextColor());
+  }
+
+  void SetupLabel(views::Label* label) {
+    label->SetTextContext(CONTEXT_CALENDAR_LABEL);
+    label->SetAutoColorReadabilityEnabled(false);
+    label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_TO_HEAD);
+  }
+
+ private:
+  // This `date_`'s month and year is used to create this view.
+  base::Time date_;
+
+  // The name of the `date_` month.
+  std::u16string month_name_;
+
+  // The month label in the view.
+  views::Label* const month_label_ = nullptr;
+
+  // The year label in the view.
+  views::Label* year_label_ = nullptr;
+};
+
 CalendarView::CalendarView(DetailedViewDelegate* delegate,
                            UnifiedSystemTrayController* controller,
                            CalendarViewController* calendar_view_controller)
@@ -123,6 +195,7 @@
   header_ = TrayPopupUtils::CreateDefaultLabel();
   header_->SetText(calendar_view_controller_->GetOnScreenMonthName());
   header_->SetTextContext(CONTEXT_CALENDAR_LABEL);
+  header_->SetAutoColorReadabilityEnabled(false);
   header_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_TO_HEAD);
 
   header_year_ = TrayPopupUtils::CreateDefaultLabel();
@@ -130,9 +203,10 @@
       calendar_utils::GetExploded(
           calendar_view_controller_->GetOnScreenMonthFirstDay())
           .year)));
-  header_year_->SetBorder(
-      views::CreateEmptyBorder(0, kLabelTextInBetweenPadding, 0, 0));
+  header_year_->SetBorder(views::CreateEmptyBorder(
+      0, kLabelTextInBetweenPadding, 0, kLabelTextInBetweenPadding));
   header_year_->SetTextContext(CONTEXT_CALENDAR_LABEL);
+  header_->SetAutoColorReadabilityEnabled(false);
   header_year_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_TO_HEAD);
 
   TriView* tri_view = TrayPopupUtils::CreateDefaultRowView();
@@ -213,17 +287,15 @@
 }
 
 void CalendarView::SetMonthViews() {
-  previous_label_ =
-      AddLabelWithId(calendar_view_controller_->GetPreviousMonthName());
+  previous_label_ = AddLabelWithId(LabelType::PREVIOUS);
   previous_month_ =
       AddMonth(calendar_view_controller_->GetPreviousMonthFirstDay());
 
-  current_label_ =
-      AddLabelWithId(calendar_view_controller_->GetOnScreenMonthName());
+  current_label_ = AddLabelWithId(LabelType::CURRENT);
   current_month_ =
       AddMonth(calendar_view_controller_->GetOnScreenMonthFirstDay());
 
-  next_label_ = AddLabelWithId(calendar_view_controller_->GetNextMonthName());
+  next_label_ = AddLabelWithId(LabelType::NEXT);
   next_month_ = AddMonth(calendar_view_controller_->GetNextMonthFirstDay());
 }
 
@@ -299,13 +371,9 @@
   ScrollToToday();
 }
 
-views::Label* CalendarView::AddLabelWithId(std::u16string label_string,
-                                           bool add_at_front) {
-  auto label = std::make_unique<CalendarLabel>(label_string);
-  label->SetBorder(views::CreateEmptyBorder(kLabelVerticalPadding, 0,
-                                            kLabelVerticalPadding, 0));
-  label->SetTextContext(CONTEXT_CALENDAR_LABEL);
-  label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_TO_HEAD);
+views::View* CalendarView::AddLabelWithId(LabelType type, bool add_at_front) {
+  auto label =
+      std::make_unique<MonthYearHeaderView>(type, calendar_view_controller_);
   if (add_at_front)
     return content_view_->AddChildViewAt(std::move(label), 0);
   return content_view_->AddChildView(std::move(label));
@@ -365,9 +433,8 @@
   previous_month_ =
       AddMonth(calendar_view_controller_->GetPreviousMonthFirstDay(),
                /*add_at_front=*/true);
-  previous_label_ =
-      AddLabelWithId(calendar_view_controller_->GetPreviousMonthName(),
-                     /*add_at_front=*/true);
+  previous_label_ = AddLabelWithId(LabelType::PREVIOUS,
+                                   /*add_at_front=*/true);
 
   // After adding a new month in the content, the current position stays the
   // same but below the added view the each view's position has changed to
@@ -399,7 +466,7 @@
   current_label_ = next_label_;
   current_month_ = next_month_;
 
-  next_label_ = AddLabelWithId(calendar_view_controller_->GetNextMonthName());
+  next_label_ = AddLabelWithId(LabelType::NEXT);
   next_month_ = AddMonth(calendar_view_controller_->GetNextMonthFirstDay());
 
   // Same as adding previous views. We need to remove the height of the
diff --git a/ash/system/time/calendar_view.h b/ash/system/time/calendar_view.h
index 6a377e0..fb3780f 100644
--- a/ash/system/time/calendar_view.h
+++ b/ash/system/time/calendar_view.h
@@ -11,6 +11,7 @@
 #include "ash/system/unified/unified_system_tray_controller.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/scroll_view.h"
+#include "ui/views/view.h"
 
 namespace views {
 
@@ -55,6 +56,15 @@
                                   int info_accessible_name_id) override;
 
  private:
+  // The header of each month view which shows the month's name. If the year of
+  // this month is not the same as the current month, the year is also shown in
+  // this view.
+  class MonthYearHeaderView;
+
+  // The types to create the `MonthYearHeaderView` which are in corresponding to
+  // the 3 months: `previous_month_`, `current_month_` and `next_month_`.
+  enum LabelType { PREVIOUS, CURRENT, NEXT };
+
   friend class CalendarViewTest;
 
   // Assigns month views and labels based on the current date on screen.
@@ -67,8 +77,7 @@
   int PositionOfToday();
 
   // Adds a month label.
-  views::Label* AddLabelWithId(std::u16string label_string,
-                               bool add_at_front = false);
+  views::View* AddLabelWithId(LabelType type, bool add_at_front = false);
 
   // Adds a `CalendarMonthView`.
   CalendarMonthView* AddMonth(base::Time month_first_date,
@@ -107,9 +116,9 @@
 
   // The following is owned by `CalendarView`.
   views::ScrollView* scroll_view_ = nullptr;
-  views::Label* current_label_ = nullptr;
-  views::Label* previous_label_ = nullptr;
-  views::Label* next_label_ = nullptr;
+  views::View* current_label_ = nullptr;
+  views::View* previous_label_ = nullptr;
+  views::View* next_label_ = nullptr;
   CalendarMonthView* previous_month_ = nullptr;
   CalendarMonthView* current_month_ = nullptr;
   CalendarMonthView* next_month_ = nullptr;
diff --git a/ash/system/time/calendar_view_unittest.cc b/ash/system/time/calendar_view_unittest.cc
index a9a27b5..5bafd99 100644
--- a/ash/system/time/calendar_view_unittest.cc
+++ b/ash/system/time/calendar_view_unittest.cc
@@ -56,9 +56,37 @@
   CalendarView* calendar_view() { return calendar_view_.get(); }
   views::ScrollView* scroll_view_() { return calendar_view_->scroll_view_; }
 
-  views::Label* previous_label() { return calendar_view_->previous_label_; }
-  views::Label* current_label() { return calendar_view_->current_label_; }
-  views::Label* next_label() { return calendar_view_->next_label_; }
+  views::View* previous_label() { return calendar_view_->previous_label_; }
+  views::View* current_label() { return calendar_view_->current_label_; }
+  views::View* next_label() { return calendar_view_->next_label_; }
+
+  std::u16string GetPreviousLabelText() {
+    std::u16string month_text =
+        static_cast<views::Label*>(previous_label()->children()[0])->GetText();
+    if (previous_label()->children().size() > 1) {
+      month_text += static_cast<views::Label*>(previous_label()->children()[1])
+                        ->GetText();
+    }
+    return month_text;
+  }
+  std::u16string GetCurrentLabelText() {
+    std::u16string month_text =
+        static_cast<views::Label*>(current_label()->children()[0])->GetText();
+    if (current_label()->children().size() > 1) {
+      month_text +=
+          static_cast<views::Label*>(current_label()->children()[1])->GetText();
+    }
+    return month_text;
+  }
+  std::u16string GetNextLabelText() {
+    std::u16string month_text =
+        static_cast<views::Label*>(next_label()->children()[0])->GetText();
+    if (next_label()->children().size() > 1) {
+      month_text +=
+          static_cast<views::Label*>(next_label()->children()[1])->GetText();
+    }
+    return month_text;
+  }
   CalendarMonthView* previous_month() {
     return calendar_view_->previous_month_;
   }
@@ -94,9 +122,9 @@
   ASSERT_TRUE(base::Time::FromString("24 Aug 2021 10:00 GMT", &date));
   CreateCalendarView(date);
 
-  EXPECT_EQ(u"July", previous_label()->GetText());
-  EXPECT_EQ(u"August", current_label()->GetText());
-  EXPECT_EQ(u"September", next_label()->GetText());
+  EXPECT_EQ(u"July", GetPreviousLabelText());
+  EXPECT_EQ(u"August", GetCurrentLabelText());
+  EXPECT_EQ(u"September", GetNextLabelText());
   EXPECT_EQ(u"August", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
@@ -115,9 +143,9 @@
   ASSERT_TRUE(base::Time::FromString("24 Dec 2021 10:00 GMT", &dec_date));
   CreateCalendarView(dec_date);
 
-  EXPECT_EQ(u"November", previous_label()->GetText());
-  EXPECT_EQ(u"December", current_label()->GetText());
-  EXPECT_EQ(u"January", next_label()->GetText());
+  EXPECT_EQ(u"November", GetPreviousLabelText());
+  EXPECT_EQ(u"December", GetCurrentLabelText());
+  EXPECT_EQ(u"January2022", GetNextLabelText());
   EXPECT_EQ(u"December", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
@@ -138,9 +166,9 @@
 
   CreateCalendarView(date);
 
-  EXPECT_EQ(u"September", previous_label()->GetText());
-  EXPECT_EQ(u"October", current_label()->GetText());
-  EXPECT_EQ(u"November", next_label()->GetText());
+  EXPECT_EQ(u"September", GetPreviousLabelText());
+  EXPECT_EQ(u"October", GetCurrentLabelText());
+  EXPECT_EQ(u"November", GetNextLabelText());
   EXPECT_EQ(u"October", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
@@ -149,25 +177,25 @@
   // the target position.
   scroll_view_()->ScrollToPosition(scroll_view_()->vertical_scroll_bar(), 400);
 
-  EXPECT_EQ(u"October", previous_label()->GetText());
-  EXPECT_EQ(u"November", current_label()->GetText());
-  EXPECT_EQ(u"December", next_label()->GetText());
+  EXPECT_EQ(u"October", GetPreviousLabelText());
+  EXPECT_EQ(u"November", GetCurrentLabelText());
+  EXPECT_EQ(u"December", GetNextLabelText());
   EXPECT_EQ(u"November", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   scroll_view_()->ScrollToPosition(scroll_view_()->vertical_scroll_bar(), 400);
 
-  EXPECT_EQ(u"November", previous_label()->GetText());
-  EXPECT_EQ(u"December", current_label()->GetText());
-  EXPECT_EQ(u"January", next_label()->GetText());
+  EXPECT_EQ(u"November", GetPreviousLabelText());
+  EXPECT_EQ(u"December", GetCurrentLabelText());
+  EXPECT_EQ(u"January2022", GetNextLabelText());
   EXPECT_EQ(u"December", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   scroll_view_()->ScrollToPosition(scroll_view_()->vertical_scroll_bar(), 400);
 
-  EXPECT_EQ(u"December", previous_label()->GetText());
-  EXPECT_EQ(u"January", current_label()->GetText());
-  EXPECT_EQ(u"February", next_label()->GetText());
+  EXPECT_EQ(u"December", GetPreviousLabelText());
+  EXPECT_EQ(u"January2022", GetCurrentLabelText());
+  EXPECT_EQ(u"February2022", GetNextLabelText());
   EXPECT_EQ(u"January", header_()->GetText());
   EXPECT_EQ(u"2022", header_year_()->GetText());
 }
@@ -185,58 +213,58 @@
 
   CreateCalendarView(date);
 
-  EXPECT_EQ(u"September", previous_label()->GetText());
-  EXPECT_EQ(u"October", current_label()->GetText());
-  EXPECT_EQ(u"November", next_label()->GetText());
+  EXPECT_EQ(u"September", GetPreviousLabelText());
+  EXPECT_EQ(u"October", GetCurrentLabelText());
+  EXPECT_EQ(u"November", GetNextLabelText());
   EXPECT_EQ(u"October", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   ScrollDownOneMonth();
 
-  EXPECT_EQ(u"October", previous_label()->GetText());
-  EXPECT_EQ(u"November", current_label()->GetText());
-  EXPECT_EQ(u"December", next_label()->GetText());
+  EXPECT_EQ(u"October", GetPreviousLabelText());
+  EXPECT_EQ(u"November", GetCurrentLabelText());
+  EXPECT_EQ(u"December", GetNextLabelText());
   EXPECT_EQ(u"November", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   ScrollDownOneMonth();
 
-  EXPECT_EQ(u"November", previous_label()->GetText());
-  EXPECT_EQ(u"December", current_label()->GetText());
-  EXPECT_EQ(u"January", next_label()->GetText());
+  EXPECT_EQ(u"November", GetPreviousLabelText());
+  EXPECT_EQ(u"December", GetCurrentLabelText());
+  EXPECT_EQ(u"January2022", GetNextLabelText());
   EXPECT_EQ(u"December", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   ScrollDownOneMonth();
 
-  EXPECT_EQ(u"December", previous_label()->GetText());
-  EXPECT_EQ(u"January", current_label()->GetText());
-  EXPECT_EQ(u"February", next_label()->GetText());
+  EXPECT_EQ(u"December", GetPreviousLabelText());
+  EXPECT_EQ(u"January2022", GetCurrentLabelText());
+  EXPECT_EQ(u"February2022", GetNextLabelText());
   EXPECT_EQ(u"January", header_()->GetText());
   EXPECT_EQ(u"2022", header_year_()->GetText());
 
   ScrollUpOneMonth();
 
-  EXPECT_EQ(u"November", previous_label()->GetText());
-  EXPECT_EQ(u"December", current_label()->GetText());
-  EXPECT_EQ(u"January", next_label()->GetText());
+  EXPECT_EQ(u"November", GetPreviousLabelText());
+  EXPECT_EQ(u"December", GetCurrentLabelText());
+  EXPECT_EQ(u"January2022", GetNextLabelText());
   EXPECT_EQ(u"December", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 
   ScrollDownOneMonth();
 
-  EXPECT_EQ(u"December", previous_label()->GetText());
-  EXPECT_EQ(u"January", current_label()->GetText());
-  EXPECT_EQ(u"February", next_label()->GetText());
+  EXPECT_EQ(u"December", GetPreviousLabelText());
+  EXPECT_EQ(u"January2022", GetCurrentLabelText());
+  EXPECT_EQ(u"February2022", GetNextLabelText());
   EXPECT_EQ(u"January", header_()->GetText());
   EXPECT_EQ(u"2022", header_year_()->GetText());
 
   // Goes back to the landing view.
   ResetToToday();
 
-  EXPECT_EQ(u"September", previous_label()->GetText());
-  EXPECT_EQ(u"October", current_label()->GetText());
-  EXPECT_EQ(u"November", next_label()->GetText());
+  EXPECT_EQ(u"September", GetPreviousLabelText());
+  EXPECT_EQ(u"October", GetCurrentLabelText());
+  EXPECT_EQ(u"November", GetNextLabelText());
   EXPECT_EQ(u"October", header_()->GetText());
   EXPECT_EQ(u"2021", header_year_()->GetText());
 }
diff --git a/ash/system/tray/DEPS b/ash/system/tray/DEPS
new file mode 100644
index 0000000..118bfa7
--- /dev/null
+++ b/ash/system/tray/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+  # TODO(crbug/1251346): Remove.
+  "tray_background_view_unittest.cc": [
+    "+components/user_manager/user_manager.h",
+  ],
+}
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc
index a7239c9..177734ce 100644
--- a/ash/test/ash_test_helper.cc
+++ b/ash/test/ash_test_helper.cc
@@ -30,6 +30,7 @@
 #include "ash/test/ash_test_views_delegate.h"
 #include "ash/test/toplevel_window.h"
 #include "ash/test_shell_delegate.h"
+#include "ash/wallpaper/test_wallpaper_controller_client.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "ash/wm/overview/overview_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
@@ -270,6 +271,13 @@
   Shell::CreateInstance(std::move(shell_init_params));
   Shell* shell = Shell::Get();
 
+  // Set up a test wallpaper controller client before signing in any users. At
+  // the time a user logs in, Wallpaper controller relies on
+  // WallpaperControllerClient to check if user data should be synced.
+  wallpaper_controller_client_ =
+      std::make_unique<TestWallpaperControllerClient>();
+  shell->wallpaper_controller()->SetClient(wallpaper_controller_client_.get());
+
   // Disable the notification delay timer used to prevent non system
   // notifications from showing up right after login. This needs to be done
   // before any user sessions are added since the delay timer starts right
diff --git a/ash/test/ash_test_helper.h b/ash/test/ash_test_helper.h
index 3c8e54a3..ea53e36 100644
--- a/ash/test/ash_test_helper.h
+++ b/ash/test/ash_test_helper.h
@@ -51,6 +51,7 @@
 class AmbientAshTestHelper;
 class TestKeyboardControllerObserver;
 class TestNewWindowDelegateProvider;
+class TestWallpaperControllerClient;
 
 // A helper class that does common initialization required for Ash. Creates a
 // root window and an ash::Shell instance with a test delegate.
@@ -161,6 +162,7 @@
   std::unique_ptr<TestKeyboardControllerObserver>
       test_keyboard_controller_observer_;
   std::unique_ptr<AmbientAshTestHelper> ambient_ash_test_helper_;
+  std::unique_ptr<TestWallpaperControllerClient> wallpaper_controller_client_;
 
   // InputMethodManager is not owned by this class. It is stored in a
   // global that is registered via InputMethodManager::Initialize().
diff --git a/ash/wallpaper/DEPS b/ash/wallpaper/DEPS
index cbd7c55..670d4dd3 100644
--- a/ash/wallpaper/DEPS
+++ b/ash/wallpaper/DEPS
@@ -1,3 +1,13 @@
 include_rules = [
   "+services/data_decoder/public",
 ]
+
+specific_include_rules = {
+  # TODO(crbug/1251346): Remove.
+  "wallpaper_controller_impl.cc": [
+    "+components/user_manager/user_manager.h",
+  ],
+  "wallpaper_controller_unittest.cc": [
+    "+components/user_manager",
+  ],
+}
diff --git a/ash/wallpaper/wallpaper_controller_impl.h b/ash/wallpaper/wallpaper_controller_impl.h
index f3238dc..80fd9ed 100644
--- a/ash/wallpaper/wallpaper_controller_impl.h
+++ b/ash/wallpaper/wallpaper_controller_impl.h
@@ -366,7 +366,7 @@
   FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest, BasicReparenting);
   FRIEND_TEST_ALL_PREFIXES(WallpaperControllerTest,
                            WallpaperMovementDuringUnlock);
-  friend class WallpaperControllerTest;
+  friend class WallpaperControllerTestBase;
   friend class WallpaperControllerTestApi;
 
   enum WallpaperMode { WALLPAPER_NONE, WALLPAPER_IMAGE };
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index b4ac145..1be802cb 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -356,14 +356,13 @@
 
 }  // namespace
 
-class WallpaperControllerTest : public AshTestBase {
+class WallpaperControllerTestBase : public AshTestBase {
  public:
-  WallpaperControllerTest() = default;
+  WallpaperControllerTestBase() = default;
 
-  WallpaperControllerTest(const WallpaperControllerTest&) = delete;
-  WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete;
-
-  ~WallpaperControllerTest() override = default;
+  WallpaperControllerTestBase(const WallpaperControllerTestBase&) = delete;
+  WallpaperControllerTestBase& operator=(const WallpaperControllerTestBase&) =
+      delete;
 
   void SetUp() override {
     AshTestBase::SetUp();
@@ -667,7 +666,37 @@
   data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
 };
 
-TEST_F(WallpaperControllerTest, Client) {
+class WallpaperControllerTest : public WallpaperControllerTestBase,
+                                public testing::WithParamInterface<bool> {
+ public:
+  WallpaperControllerTest() = default;
+
+  WallpaperControllerTest(const WallpaperControllerTest&) = delete;
+  WallpaperControllerTest& operator=(const WallpaperControllerTest&) = delete;
+
+  ~WallpaperControllerTest() override = default;
+
+  void SetUp() override {
+    if (GetParam()) {
+      scoped_feature_list_.InitWithFeatures(
+          {ash::features::kWallpaperWebUI,
+           ash::features::kWallpaperFullScreenPreview},
+          {});
+    } else {
+      scoped_feature_list_.InitWithFeatures(
+          {}, {ash::features::kWallpaperWebUI,
+               ash::features::kWallpaperFullScreenPreview});
+    }
+    WallpaperControllerTestBase::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All, WallpaperControllerTest, testing::Bool());
+
+TEST_P(WallpaperControllerTest, Client) {
   base::FilePath empty_path;
   controller_->Init(empty_path, empty_path, empty_path, empty_path);
 
@@ -677,7 +706,7 @@
   EXPECT_EQ(1u, client_.open_count());
 }
 
-TEST_F(WallpaperControllerTest, BasicReparenting) {
+TEST_P(WallpaperControllerTest, BasicReparenting) {
   WallpaperControllerImpl* controller = Shell::Get()->wallpaper_controller();
   controller->CreateEmptyWallpaperForTesting();
 
@@ -699,7 +728,7 @@
   EXPECT_EQ(0, ChildCountForContainer(kLockScreenWallpaperId));
 }
 
-TEST_F(WallpaperControllerTest, SwitchWallpapersWhenNewWallpaperAnimationEnds) {
+TEST_P(WallpaperControllerTest, SwitchWallpapersWhenNewWallpaperAnimationEnds) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -722,7 +751,7 @@
 
 // Test for crbug.com/149043 "Unlock screen, no launcher appears". Ensure we
 // move all wallpaper views if there are more than one.
-TEST_F(WallpaperControllerTest, WallpaperMovementDuringUnlock) {
+TEST_P(WallpaperControllerTest, WallpaperMovementDuringUnlock) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -774,7 +803,7 @@
 
 // Test for crbug.com/156542. Animating wallpaper should immediately finish
 // animation and replace current wallpaper before next animation starts.
-TEST_F(WallpaperControllerTest, ChangeWallpaperQuick) {
+TEST_P(WallpaperControllerTest, ChangeWallpaperQuick) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -804,7 +833,7 @@
   EXPECT_FALSE(widget_controller->IsAnimating());
 }
 
-TEST_F(WallpaperControllerTest, ResizeCustomWallpaper) {
+TEST_P(WallpaperControllerTest, ResizeCustomWallpaper) {
   UpdateDisplay("320x200");
 
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
@@ -830,7 +859,7 @@
   EXPECT_TRUE(resized_image.BackedBySameObjectAs(controller_->GetWallpaper()));
 }
 
-TEST_F(WallpaperControllerTest, GetMaxDisplaySize) {
+TEST_P(WallpaperControllerTest, GetMaxDisplaySize) {
   // Device scale factor shouldn't affect the native size.
   UpdateDisplay("1000x300*2");
   EXPECT_EQ("1000x300",
@@ -864,7 +893,7 @@
 
 // Test that the wallpaper is always fitted to the native display resolution
 // when the layout is WALLPAPER_LAYOUT_CENTER to prevent blurry images.
-TEST_F(WallpaperControllerTest, DontScaleWallpaperWithCenterLayout) {
+TEST_P(WallpaperControllerTest, DontScaleWallpaperWithCenterLayout) {
   // We cannot short-circuit animations for this test.
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
@@ -940,7 +969,7 @@
   }
 }
 
-TEST_F(WallpaperControllerTest, ShouldCalculateColorsBasedOnImage) {
+TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnImage) {
   EnableShelfColoring();
   EXPECT_TRUE(ShouldCalculateColors());
 
@@ -948,7 +977,7 @@
   EXPECT_FALSE(ShouldCalculateColors());
 }
 
-TEST_F(WallpaperControllerTest, ShouldCalculateColorsBasedOnSessionState) {
+TEST_P(WallpaperControllerTest, ShouldCalculateColorsBasedOnSessionState) {
   EnableShelfColoring();
 
   SetSessionState(SessionState::UNKNOWN);
@@ -973,7 +1002,7 @@
   EXPECT_FALSE(ShouldCalculateColors());
 }
 
-TEST_F(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) {
+TEST_P(WallpaperControllerTest, EnableShelfColoringNotifiesObservers) {
   TestWallpaperControllerObserver observer(controller_);
   EXPECT_EQ(0, observer.colors_changed_count());
 
@@ -984,57 +1013,7 @@
   EXPECT_EQ(1, observer.colors_changed_count());
 }
 
-TEST_F(WallpaperControllerTest, SetCustomWallpaper) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
-  gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
-  WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
-
-  SimulateUserLogin(account_id_1);
-
-  // Set a custom wallpaper for |kUser1|. Verify the wallpaper is set
-  // successfully and wallpaper info is updated.
-  ClearWallpaperCount();
-  controller_->SetCustomWallpaper(account_id_1, file_name_1, layout, image,
-                                  false /*preview_mode=*/);
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
-  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
-  WallpaperInfo wallpaper_info;
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info));
-  WallpaperInfo expected_wallpaper_info(
-      base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
-      WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
-  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
-  EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
-
-  // Now set another custom wallpaper for |kUser1|. Verify that the on-screen
-  // wallpaper doesn't change since |kUser1| is not active, but wallpaper info
-  // is updated properly.
-  SimulateUserLogin(account_id_2);
-  const SkColor custom_wallpaper_color = SK_ColorCYAN;
-  image = CreateImage(640, 480, custom_wallpaper_color);
-  ClearWallpaperCount();
-  controller_->SetCustomWallpaper(account_id_1, file_name_1, layout, image,
-                                  false /*preview_mode=*/);
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(0, GetWallpaperCount());
-  EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
-  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info));
-  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
-
-  // Verify the updated wallpaper is shown after |kUser1| becomes active again.
-  SimulateUserLogin(account_id_1);
-  ClearWallpaperCount();
-  controller_->ShowUserWallpaper(account_id_1);
-  RunAllTasksUntilIdle();
-  EXPECT_EQ(1, GetWallpaperCount());
-  EXPECT_EQ(custom_wallpaper_color, GetWallpaperColor());
-}
-
-TEST_F(WallpaperControllerTest, SetOnlineWallpaperIfExists) {
+TEST_P(WallpaperControllerTest, SetOnlineWallpaperIfExists) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER_CROPPED;
@@ -1108,7 +1087,7 @@
   EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
 }
 
-TEST_F(WallpaperControllerTest, SetOnlineWallpaperFromDataSavesFile) {
+TEST_P(WallpaperControllerTest, SetOnlineWallpaperFromDataSavesFile) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -1146,7 +1125,7 @@
   run_loop->Run();
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_P(WallpaperControllerTest,
        UpdatePrimaryUserWallpaperWhileSecondUserActive) {
   SetBypassDecode();
   WallpaperInfo wallpaper_info;
@@ -1193,7 +1172,7 @@
   EXPECT_EQ(wallpaper_info, expected_wallpaper_info_2);
 }
 
-TEST_F(WallpaperControllerTest, SetOnlineWallpaper) {
+TEST_P(WallpaperControllerTest, SetOnlineWallpaper) {
   SetBypassDecode();
 
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
@@ -1242,7 +1221,7 @@
   run_loop->Run();
 }
 
-TEST_F(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
+TEST_P(WallpaperControllerTest, SetAndRemovePolicyWallpaper) {
   SetBypassDecode();
   // Simulate the login screen.
   ClearLogin();
@@ -1315,7 +1294,7 @@
   EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kDefault);
 }
 
-TEST_F(WallpaperControllerTest, RemovePolicyWallpaperNoOp) {
+TEST_P(WallpaperControllerTest, RemovePolicyWallpaperNoOp) {
   auto verify_custom_wallpaper_info = [&]() {
     EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
     EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
@@ -1349,7 +1328,7 @@
   verify_custom_wallpaper_info();
 }
 
-TEST_F(WallpaperControllerTest, SetThirdPartyWallpaper) {
+TEST_P(WallpaperControllerTest, SetThirdPartyWallpaper) {
   SetBypassDecode();
   SimulateUserLogin(account_id_1);
 
@@ -1418,7 +1397,7 @@
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
+TEST_P(WallpaperControllerTest, SetDefaultWallpaperForRegularAccount) {
   CreateDefaultWallpapers();
   SimulateUserLogin(account_id_1);
 
@@ -1491,7 +1470,7 @@
   EXPECT_EQ(wallpaper_info, default_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
+TEST_P(WallpaperControllerTest, SetDefaultWallpaperForChildAccount) {
   CreateDefaultWallpapers();
 
   fake_user_manager_->AddChildUser(kChildAccountId);
@@ -1528,7 +1507,7 @@
 // Verify that the |ShowWallpaperImage| will be called with the default image
 // for the guest session only even if there's a policy that has been set for
 // another user which invokes |SetPolicyWallpaper|.
-TEST_F(WallpaperControllerTest,
+TEST_P(WallpaperControllerTest,
        SetDefaultWallpaperForGuestSessionUnaffectedByWallpaperPolicy) {
   SetBypassDecode();
   // Simulate the login screen.
@@ -1591,7 +1570,7 @@
             GetDecodeFilePaths()[0]);
 }
 
-TEST_F(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
+TEST_P(WallpaperControllerTest, SetDefaultWallpaperForGuestSession) {
   CreateDefaultWallpapers();
 
   // First, simulate setting a custom wallpaper for a regular user.
@@ -1638,7 +1617,7 @@
             GetDecodeFilePaths()[0]);
 }
 
-TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
+TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestInKioskMode) {
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin("kiosk", user_manager::USER_TYPE_KIOSK_APP);
 
@@ -1685,12 +1664,12 @@
 }
 
 // Disable the wallpaper setting for public session since it is ephemeral.
-TEST_F(WallpaperControllerTest, NotShowWallpaperSettingInPublicSession) {
+TEST_P(WallpaperControllerTest, NotShowWallpaperSettingInPublicSession) {
   SimulateUserLogin("public_session", user_manager::USER_TYPE_PUBLIC_ACCOUNT);
   EXPECT_FALSE(controller_->ShouldShowWallpaperSetting());
 }
 
-TEST_F(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
+TEST_P(WallpaperControllerTest, IgnoreWallpaperRequestWhenPolicyIsEnforced) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -1748,7 +1727,7 @@
   EXPECT_EQ(wallpaper_info, policy_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, VerifyWallpaperCache) {
+TEST_P(WallpaperControllerTest, VerifyWallpaperCache) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   SimulateUserLogin(account_id_1);
@@ -1806,7 +1785,7 @@
 
 // Tests that the appropriate wallpaper (large vs. small) is shown depending
 // on the desktop resolution.
-TEST_F(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
+TEST_P(WallpaperControllerTest, ShowCustomWallpaperWithCorrectResolution) {
   CreateDefaultWallpapers();
   const base::FilePath small_custom_wallpaper_path =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -1871,7 +1850,7 @@
 
 // After the display is rotated, the sign in wallpaper should be kept. Test for
 // crbug.com/794725.
-TEST_F(WallpaperControllerTest, SigninWallpaperIsKeptAfterRotation) {
+TEST_P(WallpaperControllerTest, SigninWallpaperIsKeptAfterRotation) {
   CreateDefaultWallpapers();
 
   UpdateDisplay("800x600");
@@ -1900,7 +1879,7 @@
 }
 
 // Display size change should trigger wallpaper reload.
-TEST_F(WallpaperControllerTest, ReloadWallpaper) {
+TEST_P(WallpaperControllerTest, ReloadWallpaper) {
   CreateAndSaveWallpapers(account_id_1);
 
   // Show a user wallpaper.
@@ -1960,7 +1939,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_F(WallpaperControllerTest, UpdateCustomWallpaperLayout) {
+TEST_P(WallpaperControllerTest, UpdateCustomWallpaperLayout) {
   SetBypassDecode();
   gfx::ImageSkia image = CreateImage(640, 480, kSmallCustomWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_STRETCH;
@@ -2030,7 +2009,7 @@
 // Tests that if a user who has a custom wallpaper is removed from the device,
 // only the directory that contains the user's custom wallpapers gets removed.
 // The other user's custom wallpaper is not affected.
-TEST_F(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
+TEST_P(WallpaperControllerTest, RemoveUserWithCustomWallpaper) {
   SimulateUserLogin(account_id_1);
   base::FilePath small_wallpaper_path_1 =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -2061,7 +2040,7 @@
 
 // Tests that if a user who has a default wallpaper is removed from the device,
 // the other user's custom wallpaper is not affected.
-TEST_F(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
+TEST_P(WallpaperControllerTest, RemoveUserWithDefaultWallpaper) {
   SimulateUserLogin(account_id_1);
   base::FilePath small_wallpaper_path_1 =
       GetCustomWallpaperPath(WallpaperControllerImpl::kSmallWallpaperSubDir,
@@ -2081,7 +2060,7 @@
   EXPECT_TRUE(base::PathExists(small_wallpaper_path_1));
 }
 
-TEST_F(WallpaperControllerTest, IsActiveUserWallpaperControlledByPolicy) {
+TEST_P(WallpaperControllerTest, IsActiveUserWallpaperControlledByPolicy) {
   SetBypassDecode();
   // Simulate the login screen. Verify that it returns false since there's no
   // active user.
@@ -2105,7 +2084,7 @@
   EXPECT_FALSE(controller_->IsActiveUserWallpaperControlledByPolicy());
 }
 
-TEST_F(WallpaperControllerTest, WallpaperBlur) {
+TEST_P(WallpaperControllerTest, WallpaperBlur) {
   TestWallpaperControllerObserver observer(controller_);
 
   ASSERT_TRUE(controller_->IsBlurAllowedForLockState());
@@ -2141,7 +2120,7 @@
   EXPECT_EQ(3, observer.blur_changed_count());
 }
 
-TEST_F(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
+TEST_P(WallpaperControllerTest, WallpaperBlurDuringLockScreenTransition) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
 
@@ -2188,7 +2167,7 @@
             wallpaper_view()->layer()->parent()->children()[1]->type());
 }
 
-TEST_F(WallpaperControllerTest, LockDuringOverview) {
+TEST_P(WallpaperControllerTest, LockDuringOverview) {
   gfx::ImageSkia image = CreateImage(600, 400, kWallpaperColor);
   controller_->ShowWallpaperImage(
       image, CreateWallpaperInfo(WALLPAPER_LAYOUT_CENTER),
@@ -2215,7 +2194,7 @@
   ASSERT_EQ(30, wallpaper_view->blur_sigma());
 }
 
-TEST_F(WallpaperControllerTest, DontLeakShieldView) {
+TEST_P(WallpaperControllerTest, DontLeakShieldView) {
   SetSessionState(SessionState::LOCKED);
   views::View* shield_view = wallpaper_view()->shield_view_for_testing();
   ASSERT_TRUE(shield_view);
@@ -2225,7 +2204,7 @@
   EXPECT_EQ(nullptr, view_tracker.view());
 }
 
-TEST_F(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) {
+TEST_P(WallpaperControllerTest, OnlyShowDevicePolicyWallpaperOnLoginScreen) {
   SetBypassDecode();
 
   // Verify the device policy wallpaper is shown on login screen.
@@ -2264,7 +2243,7 @@
   EXPECT_FALSE(IsDevicePolicyWallpaper());
 }
 
-TEST_F(WallpaperControllerTest, ShouldShowInitialAnimationAfterBoot) {
+TEST_P(WallpaperControllerTest, ShouldShowInitialAnimationAfterBoot) {
   CreateDefaultWallpapers();
 
   // Simulate the login screen after system boot.
@@ -2300,7 +2279,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_F(WallpaperControllerTest, ShouldNotShowInitialAnimationAfterSignOut) {
+TEST_P(WallpaperControllerTest, ShouldNotShowInitialAnimationAfterSignOut) {
   CreateDefaultWallpapers();
 
   // Simulate the login screen after user sign-out. Verify that the slower
@@ -2333,7 +2312,7 @@
   EXPECT_EQ(1, GetWallpaperCount());
 }
 
-TEST_F(WallpaperControllerTest, ClosePreviewWallpaperOnOverviewStart) {
+TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnOverviewStart) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2384,7 +2363,7 @@
   EXPECT_EQ(1u, client_.close_preview_count());
 }
 
-TEST_F(WallpaperControllerTest, ClosePreviewWallpaperOnWindowCycleStart) {
+TEST_P(WallpaperControllerTest, ClosePreviewWallpaperOnWindowCycleStart) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2435,7 +2414,7 @@
   EXPECT_EQ(1u, client_.close_preview_count());
 }
 
-TEST_F(WallpaperControllerTest, ConfirmPreviewWallpaper) {
+TEST_P(WallpaperControllerTest, ConfirmPreviewWallpaper) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2544,7 +2523,7 @@
   EXPECT_EQ(user_wallpaper_info, online_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, CancelPreviewWallpaper) {
+TEST_P(WallpaperControllerTest, CancelPreviewWallpaper) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2622,7 +2601,7 @@
   EXPECT_EQ(user_wallpaper_info, default_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, WallpaperSyncedDuringPreview) {
+TEST_P(WallpaperControllerTest, WallpaperSyncedDuringPreview) {
   // Verify the user starts with a default wallpaper and the user wallpaper info
   // is initialized with default values.
   SimulateUserLogin(account_id_1);
@@ -2748,7 +2727,7 @@
   EXPECT_EQ(user_wallpaper_info, synced_online_wallpaper_info);
 }
 
-TEST_F(WallpaperControllerTest, AddFirstWallpaperAnimationEndCallback) {
+TEST_P(WallpaperControllerTest, AddFirstWallpaperAnimationEndCallback) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   std::unique_ptr<aura::Window> test_window(
@@ -2807,7 +2786,7 @@
   EXPECT_TRUE(is_third_callback_run);
 }
 
-TEST_F(WallpaperControllerTest, ShowOneShotWallpaper) {
+TEST_P(WallpaperControllerTest, ShowOneShotWallpaper) {
   gfx::ImageSkia custom_wallpaper = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
@@ -2863,7 +2842,7 @@
   EXPECT_EQ(WallpaperType::kCustomized, controller_->GetWallpaperType());
 }
 
-TEST_F(WallpaperControllerTest, OnFirstWallpaperShown) {
+TEST_P(WallpaperControllerTest, OnFirstWallpaperShown) {
   TestWallpaperControllerObserver observer(controller_);
   EXPECT_EQ(0, GetWallpaperCount());
   EXPECT_EQ(0, observer.first_shown_count());
@@ -2889,7 +2868,7 @@
 
 // Although ephemeral users' custom wallpapers are not saved to disk, they
 // should be kept within the user session. Test for https://crbug.com/825237.
-TEST_F(WallpaperControllerTest, ShowWallpaperForEphemeralUser) {
+TEST_P(WallpaperControllerTest, ShowWallpaperForEphemeralUser) {
   // Add an ephemeral user session and simulate login, like SimulateUserLogin.
   UserSession session;
   session.session_id = 0;
@@ -2935,7 +2914,7 @@
   EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
 }
 
-TEST_F(WallpaperControllerTest, AlwaysOnTopWallpaper) {
+TEST_P(WallpaperControllerTest, AlwaysOnTopWallpaper) {
   CreateDefaultWallpapers();
   SetBypassDecode();
 
@@ -2989,7 +2968,8 @@
 
 namespace {
 
-class WallpaperControllerPrefTest : public AshTestBase {
+class WallpaperControllerPrefTest : public AshTestBase,
+                                    public testing::WithParamInterface<bool> {
  public:
   WallpaperControllerPrefTest() {
     base::DictionaryValue property;
@@ -3003,13 +2983,32 @@
   }
 
   ~WallpaperControllerPrefTest() override = default;
+
+  void SetUp() override {
+    if (GetParam()) {
+      scoped_feature_list_.InitWithFeatures(
+          {ash::features::kWallpaperWebUI,
+           ash::features::kWallpaperFullScreenPreview},
+          {});
+    } else {
+      scoped_feature_list_.InitWithFeatures(
+          {}, {ash::features::kWallpaperWebUI,
+               ash::features::kWallpaperFullScreenPreview});
+    }
+    AshTestBase::SetUp();
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 }  // namespace
 
+INSTANTIATE_TEST_SUITE_P(All, WallpaperControllerPrefTest, testing::Bool());
+
 // Make sure that the display and the wallpaper view are rotated correctly at
 // startup.
-TEST_F(WallpaperControllerPrefTest, InitWithPrefs) {
+TEST_P(WallpaperControllerPrefTest, InitWithPrefs) {
   auto* wallpaper_view = Shell::GetPrimaryRootWindowController()
                              ->wallpaper_widget_controller()
                              ->wallpaper_view();
@@ -3022,7 +3021,7 @@
   EXPECT_EQ(root_window->bounds().size(), wallpaper_view->bounds().size());
 }
 
-TEST_F(WallpaperControllerTest, NoAnimationForNewRootWindowWhenLocked) {
+TEST_P(WallpaperControllerTest, NoAnimationForNewRootWindowWhenLocked) {
   ui::ScopedAnimationDurationScaleMode test_duration_mode(
       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
   SetSessionState(SessionState::LOCKED);
@@ -3038,7 +3037,7 @@
                    ->is_animating());
 }
 
-TEST_F(WallpaperControllerTest, GetWallpaperInfo) {
+TEST_P(WallpaperControllerTest, GetWallpaperInfo) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kDaily);
   controller_->SetUserWallpaperInfo(account_id_1, expected_info);
 
@@ -3047,12 +3046,95 @@
   EXPECT_EQ(expected_info, actual_info);
 }
 
-TEST_F(WallpaperControllerTest, GetWallpaperInfoNothingToGet) {
+TEST_P(WallpaperControllerTest, GetWallpaperInfoNothingToGet) {
   WallpaperInfo info;
   EXPECT_FALSE(controller_->GetUserWallpaperInfo(account_id_1, &info));
 }
 
-TEST_F(WallpaperControllerTest, SetWallpaperInfoSynced) {
+TEST_P(WallpaperControllerTest, SetWallpaperInfoLocal) {
+  WallpaperInfo info(
+      GetDummyFileName(account_id_1), WALLPAPER_LAYOUT_CENTER_CROPPED,
+      WallpaperType::kThirdParty, base::Time::Now().LocalMidnight());
+  EXPECT_TRUE(controller_->SetUserWallpaperInfo(account_id_1, info));
+  AssertWallpaperInfoInPrefs(GetLocalPrefService(), prefs::kUserWallpaperInfo,
+                             account_id_1, info);
+}
+
+// Test cases that only run with |kWallpaperWebUI| turned on.
+class WallpaperControllerWallpaperWebUiTest
+    : public WallpaperControllerTestBase {
+ public:
+  WallpaperControllerWallpaperWebUiTest() = default;
+
+  WallpaperControllerWallpaperWebUiTest(
+      const WallpaperControllerWallpaperWebUiTest&) = delete;
+  WallpaperControllerWallpaperWebUiTest& operator=(
+      const WallpaperControllerWallpaperWebUiTest&) = delete;
+
+  ~WallpaperControllerWallpaperWebUiTest() override = default;
+
+  void SetUp() override {
+    scoped_feature_list_.InitWithFeatures(
+        {features::kWallpaperWebUI, features::kWallpaperFullScreenPreview}, {});
+    WallpaperControllerTestBase::SetUp();
+  }
+
+  base::test::ScopedFeatureList& scoped_feature_list() {
+    return scoped_feature_list_;
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(WallpaperControllerWallpaperWebUiTest, SetCustomWallpaper) {
+  gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
+  WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
+
+  SimulateUserLogin(account_id_1);
+
+  // Set a custom wallpaper for |kUser1|. Verify the wallpaper is set
+  // successfully and wallpaper info is updated.
+  ClearWallpaperCount();
+  controller_->SetCustomWallpaper(account_id_1, file_name_1, layout, image,
+                                  false /*preview_mode=*/);
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(1, GetWallpaperCount());
+  EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
+  EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kCustomized);
+  WallpaperInfo wallpaper_info;
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info));
+  WallpaperInfo expected_wallpaper_info(
+      base::FilePath(wallpaper_files_id_1).Append(file_name_1).value(), layout,
+      WallpaperType::kCustomized, base::Time::Now().LocalMidnight());
+  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
+  EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
+
+  // Now set another custom wallpaper for |kUser1|. Verify that the on-screen
+  // wallpaper doesn't change since |kUser1| is not active, but wallpaper info
+  // is updated properly.
+  SimulateUserLogin(account_id_2);
+  const SkColor custom_wallpaper_color = SK_ColorCYAN;
+  image = CreateImage(640, 480, custom_wallpaper_color);
+  ClearWallpaperCount();
+  controller_->SetCustomWallpaper(account_id_1, file_name_1, layout, image,
+                                  false /*preview_mode=*/);
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(0, GetWallpaperCount());
+  EXPECT_EQ(kWallpaperColor, GetWallpaperColor());
+  EXPECT_TRUE(controller_->GetUserWallpaperInfo(account_id_1, &wallpaper_info));
+  EXPECT_EQ(wallpaper_info, expected_wallpaper_info);
+
+  // Verify the updated wallpaper is shown after |kUser1| becomes active again.
+  SimulateUserLogin(account_id_1);
+  ClearWallpaperCount();
+  controller_->ShowUserWallpaper(account_id_1);
+  RunAllTasksUntilIdle();
+  EXPECT_EQ(1, GetWallpaperCount());
+  EXPECT_EQ(custom_wallpaper_color, GetWallpaperColor());
+}
+
+TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoSynced) {
   base::test::ScopedFeatureList scoped_features;
   scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
 
@@ -3062,7 +3144,7 @@
                              prefs::kSyncableWallpaperInfo, account_id_1, info);
 }
 
-TEST_F(WallpaperControllerTest, SetWallpaperInfoSyncDisabled) {
+TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoSyncDisabled) {
   base::test::ScopedFeatureList scoped_features;
   scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
 
@@ -3081,10 +3163,7 @@
                              expected_info);
 }
 
-TEST_F(WallpaperControllerTest, SetWallpaperInfoCustom) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, SetWallpaperInfoCustom) {
   WallpaperInfo synced_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, synced_info,
                           GetProfilePrefService(account_id_1),
@@ -3101,19 +3180,7 @@
                              synced_info);
 }
 
-TEST_F(WallpaperControllerTest, SetWallpaperInfoLocal) {
-  WallpaperInfo info(
-      GetDummyFileName(account_id_1), WALLPAPER_LAYOUT_CENTER_CROPPED,
-      WallpaperType::kThirdParty, base::Time::Now().LocalMidnight());
-  EXPECT_TRUE(controller_->SetUserWallpaperInfo(account_id_1, info));
-  AssertWallpaperInfoInPrefs(GetLocalPrefService(), prefs::kUserWallpaperInfo,
-                             account_id_1, info);
-}
-
-TEST_F(WallpaperControllerTest, MigrateWallpaperInfo) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateWallpaperInfo) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, expected_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3123,10 +3190,7 @@
                              expected_info);
 }
 
-TEST_F(WallpaperControllerTest, MigrateWallpaperInfoDaily) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateWallpaperInfoDaily) {
   WallpaperInfo expected_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, expected_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3137,11 +3201,8 @@
   EXPECT_EQ(client_.migrate_collection_id_from_chrome_app_count(), 1u);
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        MigrateWallpaperInfoDoesntHappenWhenSyncedInfoAlreadyExists) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   SetBypassDecode();
 
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kOnline),
@@ -3157,11 +3218,8 @@
                              synced_info);
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        ActiveUserPrefServiceChangedSyncedInfoHandledLocally) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   SimulateUserLogin(account_id_1);
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kDefault),
                           GetProfilePrefService(account_id_1),
@@ -3181,10 +3239,8 @@
   EXPECT_EQ(WallpaperType::kDefault, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest, ActiveUserPrefServiceChanged_SyncDisabled) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       ActiveUserPrefServiceChanged_SyncDisabled) {
   SimulateUserLogin(account_id_1);
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kDefault),
                           GetProfilePrefService(account_id_1),
@@ -3206,10 +3262,8 @@
   EXPECT_EQ(WallpaperType::kThirdParty, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedDefault) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       HandleWallpaperInfoSyncedDefault) {
   SimulateUserLogin(account_id_1);
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kDefault),
                           GetProfilePrefService(account_id_1),
@@ -3219,10 +3273,8 @@
   EXPECT_EQ(WallpaperType::kDefault, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedLocalIsPolicy) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       HandleWallpaperInfoSyncedLocalIsPolicy) {
   PutWallpaperInfoInPrefs(account_id_1, InfoWithType(WallpaperType::kPolicy),
                           GetLocalPrefService(), prefs::kUserWallpaperInfo);
 
@@ -3235,11 +3287,8 @@
   EXPECT_NE(WallpaperType::kDefault, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        HandleWallpaperInfoSyncedLocalIsThirdPartyAndOlder) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   WallpaperInfo local_info = InfoWithType(WallpaperType::kThirdParty);
   local_info.date = DayBeforeYesterdayish();
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
@@ -3254,11 +3303,8 @@
   EXPECT_EQ(WallpaperType::kDefault, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        HandleWallpaperInfoSyncedLocalIsThirdPartyAndNewer) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   PutWallpaperInfoInPrefs(account_id_1,
                           InfoWithType(WallpaperType::kThirdParty),
                           GetLocalPrefService(), prefs::kUserWallpaperInfo);
@@ -3274,10 +3320,7 @@
   EXPECT_EQ(WallpaperType::kThirdParty, actual_info.type);
 }
 
-TEST_F(WallpaperControllerTest, HandleWallpaperInfoSyncedOnline) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, HandleWallpaperInfoSyncedOnline) {
   SetBypassDecode();
   SimulateUserLogin(account_id_1);
 
@@ -3315,10 +3358,7 @@
   EXPECT_EQ(controller_->GetWallpaperType(), WallpaperType::kOnline);
 }
 
-TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, UpdateDailyRefreshWallpaper) {
   std::string expected{"fun_collection"};
   SimulateUserLogin(account_id_1);
 
@@ -3332,10 +3372,8 @@
   EXPECT_EQ(expected, client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaperCalledOnLogin) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       UpdateDailyRefreshWallpaperCalledOnLogin) {
   std::string expected{"fun_collection"};
   SimulateUserLogin(account_id_1);
 
@@ -3355,10 +3393,8 @@
   EXPECT_EQ(expected, client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NotEnabled) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       UpdateDailyRefreshWallpaper_NotEnabled) {
   SimulateUserLogin(account_id_1);
   controller_->SetUserWallpaperInfo(
       account_id_1,
@@ -3370,10 +3406,8 @@
   EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerTest, UpdateDailyRefreshWallpaper_NoCollectionId) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       UpdateDailyRefreshWallpaper_NoCollectionId) {
   SimulateUserLogin(account_id_1);
   controller_->SetUserWallpaperInfo(
       account_id_1,
@@ -3385,11 +3419,8 @@
   EXPECT_EQ(std::string(), client_.get_fetch_daily_refresh_wallpaper_param());
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        UpdateDailyRefreshWallpaper_TimerStartsOnPrefServiceChange) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   using base::Time;
   using base::TimeDelta;
 
@@ -3417,14 +3448,11 @@
             update_time + TimeDelta::FromHours(1) + TimeDelta::FromMinutes(1));
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        UpdateDailyRefreshWallpaper_RetryTimerTriggersOnFailedFetchInfo) {
   using base::Time;
   using base::TimeDelta;
 
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   client_.set_fetch_daily_refresh_info_fails(true);
 
   SimulateUserLogin(account_id_1);
@@ -3446,14 +3474,11 @@
   ASSERT_LE(delay, one_hour + TimeDelta::FromMinutes(1));
 }
 
-TEST_F(WallpaperControllerTest,
+TEST_F(WallpaperControllerWallpaperWebUiTest,
        UpdateDailyRefreshWallpaper_RetryTimerTriggersOnFailedFetchData) {
   using base::Time;
   using base::TimeDelta;
 
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
   SimulateUserLogin(account_id_1);
 
   controller_->SetUserWallpaperInfo(
@@ -3478,7 +3503,9 @@
   ASSERT_LE(delay, one_hour + TimeDelta::FromMinutes(1));
 }
 
-TEST_F(WallpaperControllerTest, MigrateCustomWallpaper) {
+TEST_F(WallpaperControllerWallpaperWebUiTest, MigrateCustomWallpaper) {
+  scoped_feature_list().Reset();
+  scoped_feature_list().InitWithFeatures({}, {features::kWallpaperWebUI});
   gfx::ImageSkia image = CreateImage(640, 480, kWallpaperColor);
   WallpaperLayout layout = WALLPAPER_LAYOUT_CENTER;
 
@@ -3489,17 +3516,14 @@
   RunAllTasksUntilIdle();
   ClearLogin();
 
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
+  scoped_feature_list().Reset();
+  scoped_feature_list().InitWithFeatures({features::kWallpaperWebUI}, {});
 
   SimulateUserLogin(account_id_1);
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerTest, OnGoogleDriveMounted) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, OnGoogleDriveMounted) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3509,10 +3533,8 @@
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_WallpaperIsntCustom) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       OnGoogleDriveMounted_WallpaperIsntCustom) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kOnline);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3521,10 +3543,8 @@
   EXPECT_TRUE(client_.get_save_wallpaper_to_drive_fs_account_id().empty());
 }
 
-TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_AlreadySynced) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       OnGoogleDriveMounted_AlreadySynced) {
   WallpaperInfo local_info = InfoWithType(WallpaperType::kCustomized);
   PutWallpaperInfoInPrefs(account_id_1, local_info, GetLocalPrefService(),
                           prefs::kUserWallpaperInfo);
@@ -3545,10 +3565,8 @@
   EXPECT_FALSE(client_.get_save_wallpaper_to_drive_fs_account_id().is_valid());
 }
 
-TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_OldLocalInfo) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       OnGoogleDriveMounted_OldLocalInfo) {
   WallpaperInfo local_info =
       WallpaperInfo("a_url", WALLPAPER_LAYOUT_CENTER_CROPPED,
                     WallpaperType::kCustomized, DayBeforeYesterdayish());
@@ -3571,10 +3589,8 @@
             account_id_1);
 }
 
-TEST_F(WallpaperControllerTest, OnGoogleDriveMounted_NewLocalInfo) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       OnGoogleDriveMounted_NewLocalInfo) {
   WallpaperInfo local_info = WallpaperInfo(
       "a_url", WALLPAPER_LAYOUT_CENTER_CROPPED, WallpaperType::kCustomized,
       base::Time::Now().LocalMidnight());
@@ -3594,10 +3610,7 @@
   EXPECT_EQ(account_id_1, client_.get_save_wallpaper_to_drive_fs_account_id());
 }
 
-TEST_F(WallpaperControllerTest, SetDailyRefreshCollectionId) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest, SetDailyRefreshCollectionId) {
   controller_->SetUserWallpaperInfo(
       account_id_1,
       WallpaperInfo(std::string(), absl::nullopt, std::string(),
@@ -3619,10 +3632,8 @@
             controller_->GetDailyRefreshCollectionId(account_id_1));
 }
 
-TEST_F(WallpaperControllerTest, SetDailyRefreshCollectionId_Empty) {
-  base::test::ScopedFeatureList scoped_features;
-  scoped_features.InitAndEnableFeature(features::kWallpaperWebUI);
-
+TEST_F(WallpaperControllerWallpaperWebUiTest,
+       SetDailyRefreshCollectionId_Empty) {
   std::string collection_id = "fun_collection";
   controller_->SetUserWallpaperInfo(
       account_id_1,
diff --git a/ash/webui/diagnostics_ui/diagnostics_ui.cc b/ash/webui/diagnostics_ui/diagnostics_ui.cc
index 8ccd21e..7718bfa 100644
--- a/ash/webui/diagnostics_ui/diagnostics_ui.cc
+++ b/ash/webui/diagnostics_ui/diagnostics_ui.cc
@@ -105,13 +105,16 @@
       {"diagnosticsTitle", IDS_DIAGNOSTICS_TITLE},
       {"disabledText", IDS_DIAGNOSTICS_DISABLED_TEXT},
       {"dischargeTestResultText", IDS_DISCHARGE_TEST_RESULT},
+      {"dnsGroupText", IDS_NETWORK_DIAGNOSTICS_DNS_GROUP},
       {"dnsLatencyRoutineText", IDS_NETWORK_DIAGNOSTICS_DNS_LATENCY},
       {"dnsResolutionRoutineText", IDS_NETWORK_DIAGNOSTICS_DNS_RESOLUTION},
       {"dnsResolverPresentRoutineText",
        IDS_NETWORK_DIAGNOSTICS_DNS_RESOLVER_PRESENT},
       {"ethernetLabel", IDS_NETWORK_TYPE_ETHERNET},
+      {"firewallGroupText", IDS_NETWORK_DIAGNOSTICS_FIREWALL_GROUP},
       {"gatewayCanBePingedRoutineText",
        IDS_NETWORK_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED},
+      {"gatewayRoutineText", IDS_NETWORK_DIAGNOSTICS_GATEWAY_GROUP},
       {"hasSecureWiFiConnectionRoutineText",
        IDS_NETWORK_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION},
       {"hideReportText", IDS_DIAGNOSTICS_HIDE_REPORT_TEXT},
@@ -133,6 +136,8 @@
       {"inputDeviceDescriptionTouchscreen",
        IDS_INPUT_DIAGNOSTICS_TOUCHSCREEN_DESCRIPTION},
       {"inputDeviceTest", IDS_INPUT_DIAGNOSTICS_RUN_TEST},
+      {"internetConnectivityGroupLabel",
+       IDS_DIAGNOSTICS_INTERNET_CONNECTIVITY_GROUP_LABEL},
       {"ipConfigInfoDrawerGateway",
        IDS_NETWORK_DIAGNOSTICS_IP_CONFIG_INFO_DRAWER_GATEWAY},
       {"ipConfigInfoDrawerMacAddress",
@@ -141,13 +146,16 @@
        IDS_NETWORK_DIAGNOSTICS_IP_CONFIG_INFO_DRAWER_SUBNET_MASK},
       {"ipConfigInfoDrawerTitle",
        IDS_NETWORK_DIAGNOSTICS_IP_CONFIG_INFO_DRAWER_TITLE},
+      {"lanConnectivityGroupText", IDS_NETWORK_DIAGNOSTICS_CONNECTION_GROUP},
       {"lanConnectivityRoutineText", IDS_NETWORK_DIAGNOSTICS_LAN_CONNECTIVITY},
       {"learnMore", IDS_DIANOSTICS_LEARN_MORE_LABEL},
       {"learnMoreShort", IDS_DIAGNOSTICS_LEARN_MORE_LABEL_SHORT},
+      {"localNetworkGroupLabel", IDS_DIAGNOSTICS_LOCAL_NETWORK_GROUP_LABEL},
       {"memoryAvailable", IDS_DIAGNOSTICS_MEMORY_AVAILABLE_TEXT},
       {"memoryBannerMessage", IDS_DIAGNOSTICS_MEMORY_BANNER_MESSAGE},
       {"memoryRoutineText", IDS_DIAGNOSTICS_MEMORY_ROUTINE_TEXT},
       {"memoryTitle", IDS_DIAGNOSTICS_MEMORY_TITLE},
+      {"nameResolutionGroupLabel", IDS_DIAGNOSTICS_NAME_RESOLUTION_GROUP_LABEL},
       {"networkAuthenticationLabel", IDS_NETWORK_DIAGNOSTICS_AUTHENTICATION},
       {"networkBssidLabel", IDS_ONC_WIFI_BSSID},
       {"networkChannelLabel", IDS_NETWORK_DIAGNOSTICS_CHANNEL},
@@ -183,7 +191,20 @@
       {"networkSecurityWepPskLabel", IDS_ONC_WIFI_SECURITY_WEP},
       {"networkSecurityWpaEapLabel", IDS_ONC_WIFI_SECURITY_EAP},
       {"networkSecurityWpaPskLabel", IDS_ONC_WIFI_SECURITY_PSK},
+      {"networkTechnologyCdma1xrttLabel",
+       IDS_NETWORK_DIAGNOSTICS_CELLULAR_CDMA1XRTT},
+      {"networkTechnologyEdgeLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_EDGE},
+      {"networkTechnologyEvdoLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_EVDO},
+      {"networkTechnologyGprsLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_GPRS},
+      {"networkTechnologyGsmLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_GSM},
+      {"networkTechnologyHspaLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_HSPA},
+      {"networkTechnologyHspaPlusLabel",
+       IDS_NETWORK_DIAGNOSTICS_CELLULAR_HSPA_PLUS},
       {"networkTechnologyLabel", IDS_ONC_CELLULAR_NETWORK_TECHNOLOGY},
+      {"networkTechnologyLteLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_LTE},
+      {"networkTechnologyLteAdvancedLabel",
+       IDS_NETWORK_DIAGNOSTICS_CELLULAR_LTE_ADVANCED},
+      {"networkTechnologyUmtsLabel", IDS_NETWORK_DIAGNOSTICS_CELLULAR_UMTS},
       {"notEnoughAvailableMemoryMessage",
        IDS_DIAGNOSTICS_NOT_ENOUGH_AVAILABLE_MEMORY},
       {"overviewText", IDS_DIAGNOSTICS_OVERVIEW},
@@ -191,6 +212,7 @@
       {"reconnectLinkText", IDS_DIAGNOSTICS_RECONNECT_LINK_TEXT},
       {"remainingCharge", IDS_DIAGNOSTICS_REMAINING_CHARGE_LABEL},
       {"routineEntryText", IDS_DIANOSTICS_ROUTINE_ENTRY_TEXT},
+      {"routineFailedText", IDS_DIAGNOSTICS_FAILED_TEST_TEXT},
       {"routineNameText", IDS_DIANOSTICS_ROUTINE_NAME_TEXT},
       {"runAgainButtonText", IDS_DIAGNOSTICS_RUN_AGAIN_BUTTON_TEXT},
       {"routineRemainingMin", IDS_DIAGNOSTICS_ROUTINE_REMAINING_MIN},
@@ -223,7 +245,9 @@
       {"troubleConnecting", IDS_DIAGNOSTICS_TROUBLE_CONNECTING},
       {"troubleshootingText", IDS_DIAGNOSTICS_TROUBLESHOOTING_TEXT},
       {"versionInfo", IDS_DIAGNOSTICS_VERSION_INFO_TEXT},
-      {"wifiLabel", IDS_NETWORK_TYPE_WIFI}};
+      {"wifiGroupLabel", IDS_NETWORK_DIAGNOSTICS_WIFI_GROUP},
+      {"wifiLabel", IDS_NETWORK_TYPE_WIFI},
+  };
   html_source->AddLocalizedStrings(kLocalizedStrings);
   html_source->AddLocalizedStrings(*GetDataSourceUpdate());
   html_source->UseStringsJs();
diff --git a/ash/webui/diagnostics_ui/resources/BUILD.gn b/ash/webui/diagnostics_ui/resources/BUILD.gn
index c5056bc..552d580 100644
--- a/ash/webui/diagnostics_ui/resources/BUILD.gn
+++ b/ash/webui/diagnostics_ui/resources/BUILD.gn
@@ -41,6 +41,7 @@
     ":overview_card",
     ":percent_bar_chart",
     ":realtime_cpu_chart",
+    ":routine_group",
     ":routine_list_executor",
     ":routine_result_entry",
     ":routine_result_list",
@@ -78,6 +79,7 @@
   deps = [
     ":ip_config_info_drawer",
     ":network_info",
+    ":routine_group",
     ":routine_section",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:i18n_behavior.m",
@@ -304,12 +306,20 @@
   externs_list = [ "../../../../third_party/d3/src/externs.js" ]
 }
 
+js_library("routine_group") {
+  deps = [
+    ":routine_list_executor",
+    "//ui/webui/resources/js:cr.m",
+  ]
+}
+
 js_library("routine_list_executor") {
   deps = [ "//ui/webui/resources/js:cr.m" ]
 }
 
 js_library("routine_result_entry") {
   deps = [
+    ":routine_group",
     "//third_party/polymer/v3_0/components-chromium/iron-a11y-announcer:iron-a11y-announcer",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:load_time_data.m",
@@ -318,6 +328,7 @@
 
 js_library("routine_result_list") {
   deps = [
+    ":routine_group",
     ":routine_list_executor",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
   ]
@@ -326,6 +337,7 @@
 js_library("routine_section") {
   deps = [
     ":mojo_interface_provider",
+    ":routine_group",
     ":routine_result_list",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:load_time_data.m",
diff --git a/ash/webui/diagnostics_ui/resources/cellular_info.html b/ash/webui/diagnostics_ui/resources/cellular_info.html
index f97d8f6..12b76a6e 100644
--- a/ash/webui/diagnostics_ui/resources/cellular_info.html
+++ b/ash/webui/diagnostics_ui/resources/cellular_info.html
@@ -8,7 +8,8 @@
         orientation="horizontal">
       </data-point>
       <data-point id="technology" header="[[i18n('networkTechnologyLabel')]]"
-          value="[[network.typeProperties.cellular.networkTechnology]]"
+          value="[[computeNetworkTechnologyText_(
+            network.typeProperties.cellular.networkTechnology)]]"
           orientation="horizontal">
       </data-point>
       <data-point id="roaming" header="[[i18n('networkRoamingStateLabel')]]"
diff --git a/ash/webui/diagnostics_ui/resources/cellular_info.js b/ash/webui/diagnostics_ui/resources/cellular_info.js
index d850984..fd356795 100644
--- a/ash/webui/diagnostics_ui/resources/cellular_info.js
+++ b/ash/webui/diagnostics_ui/resources/cellular_info.js
@@ -33,6 +33,44 @@
   },
 
   /**
+   * Get correct display text for known cellular network technology.
+   * @protected
+   * @return {string}
+   */
+  computeNetworkTechnologyText_() {
+    if (!this.network.typeProperties) {
+      return '';
+    }
+
+    const technology = this.network.typeProperties.cellular.networkTechnology;
+    switch (technology) {
+      case 'CDMA1XRTT':
+        return this.i18n('networkTechnologyCdma1xrttLabel');
+      case 'EDGE':
+        return this.i18n('networkTechnologyEdgeLabel');
+      case 'EVDO':
+        return this.i18n('networkTechnologyEvdoLabel');
+      case 'GPRS':
+        return this.i18n('networkTechnologyGprsLabel');
+      case 'GSM':
+        return this.i18n('networkTechnologyGsmLabel');
+      case 'HSPA':
+        return this.i18n('networkTechnologyHspaLabel');
+      case 'HSPAPlus':
+        return this.i18n('networkTechnologyHspaPlusLabel');
+      case 'LTE':
+        return this.i18n('networkTechnologyLteLabel');
+      case 'LTEAdvanced':
+        return this.i18n('networkTechnologyLteAdvancedLabel');
+      case 'UMTS':
+        return this.i18n('networkTechnologyUmtsLabel');
+      default:
+        assertNotReached();
+        return ''
+    }
+  },
+
+  /**
    * @protected
    * @return {string}
    */
diff --git a/ash/webui/diagnostics_ui/resources/connectivity_card.html b/ash/webui/diagnostics_ui/resources/connectivity_card.html
index 8866877..b35e202 100644
--- a/ash/webui/diagnostics_ui/resources/connectivity_card.html
+++ b/ash/webui/diagnostics_ui/resources/connectivity_card.html
@@ -14,9 +14,9 @@
     [[i18n('networkDefaultConnectionLabel')]]
   </div>
   <network-info network="[[network]]" slot="body"></network-info>
-  <routine-section slot="left-panel" routines="[[routines_]]"
+  <routine-section slot="left-panel" routines="[[routineGroups_]]"
       test-suite-status="{{testSuiteStatus}}"
-      routine-runtime="{{getEstimateRuntimeInMinutes_(routines_)}}"
+      routine-runtime="{{getEstimateRuntimeInMinutes_(routineGroups_)}}"
       is-active="[[isActive]]"
       hide-routine-status
       opened>
diff --git a/ash/webui/diagnostics_ui/resources/connectivity_card.js b/ash/webui/diagnostics_ui/resources/connectivity_card.js
index 221fe6e..f60d1871 100644
--- a/ash/webui/diagnostics_ui/resources/connectivity_card.js
+++ b/ash/webui/diagnostics_ui/resources/connectivity_card.js
@@ -10,11 +10,13 @@
 import './routine_section.js';
 
 import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Network, NetworkHealthProviderInterface, NetworkStateObserverInterface, NetworkStateObserverReceiver, NetworkType, RoutineType} from './diagnostics_types.js';
-import {getNetworkState, getNetworkType, getRoutinesByNetworkType} from './diagnostics_utils.js';
+import {getNetworkState, getNetworkType, getRoutineGroups} from './diagnostics_utils.js';
 import {getNetworkHealthProvider} from './mojo_interface_provider.js';
+import {RoutineGroup} from './routine_group.js';
 import {TestSuiteStatus} from './routine_list_executor.js';
 
 
@@ -48,8 +50,8 @@
       notify: true,
     },
 
-    /** @private {!Array<!RoutineType>} */
-    routines_: {
+    /** @private {!Array<!RoutineGroup>} */
+    routineGroups_: {
       type: Array,
       value: () => [],
     },
@@ -138,7 +140,8 @@
     this.macAddress_ = network.macAddress || '';
 
     if (this.testSuiteStatus === TestSuiteStatus.kNotRunning) {
-      this.routines_ = getRoutinesByNetworkType(network.type);
+      let isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics');
+      this.routineGroups_ = getRoutineGroups(network.type, isArcEnabled);
       this.getRoutineSectionElem_().runTests();
     }
 
@@ -181,7 +184,7 @@
       return;
     }
 
-    if (this.routines_.length > 0) {
+    if (this.routineGroups_.length > 0) {
       this.getRoutineSectionElem_().runTests();
     }
   },
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd b/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
index 5fa26bd..499b8af8 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_app_resources.grd
@@ -48,6 +48,7 @@
       <include name="IDR_DIAGNOSTICS_OVERVIEW_CARD_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/overview_card.js" resource_path="overview_card.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_PERCENT_BAR_CHART_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/percent_bar_chart.js" resource_path="percent_bar_chart.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_REALTIME_CPU_CHART_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/realtime_cpu_chart.js" resource_path="realtime_cpu_chart.js" use_base_dir="false" type="BINDATA"/>
+      <include name="IDR_DIAGNOSTICS_ROUTINE_GROUP_JS" file="routine_group.js" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_LIST_EXECUTOR_JS" file="routine_list_executor.js" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_RESULT_ENTRY_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/routine_result_entry.js" resource_path="routine_result_entry.js" use_base_dir="false" type="BINDATA"/>
       <include name="IDR_DIAGNOSTICS_ROUTINE_RESULT_LIST_JS" file="${root_gen_dir}/ash/webui/diagnostics_ui/resources/routine_result_list.js" resource_path="routine_result_list.js" use_base_dir="false" type="BINDATA"/>
diff --git a/ash/webui/diagnostics_ui/resources/diagnostics_utils.js b/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
index 7fa56d5..c98cf7d 100644
--- a/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
+++ b/ash/webui/diagnostics_ui/resources/diagnostics_utils.js
@@ -4,7 +4,9 @@
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {LockType, NetworkState, NetworkType, RoutineType} from './diagnostics_types.js';
+
+import {LockType, NetworkState, NetworkType, RoutineResult, RoutineType, StandardRoutineResult} from './diagnostics_types.js';
+import {RoutineGroup} from './routine_group.js';
 
 /**
  * Converts a KiB storage value to GiB and returns a fixed-point string
@@ -104,40 +106,60 @@
   }
 }
 
+
 /**
  * @param {!NetworkType} type
- * @return {!Array<!RoutineType>}
+ * @param {boolean} isArcEnabled
+ * @return {!Array<!RoutineGroup>}
  */
-export function getRoutinesByNetworkType(type) {
-  // TODO(ashleydp): Update function to support routine groups.
-  /** @type {!Array<!RoutineType>} */
-  let networkRoutines = [
-    RoutineType.kCaptivePortal,
-    RoutineType.kDnsLatency,
-    RoutineType.kDnsResolution,
-    RoutineType.kDnsResolverPresent,
-    RoutineType.kGatewayCanBePinged,
-    RoutineType.kHttpFirewall,
-    RoutineType.kHttpsFirewall,
-    RoutineType.kHttpsLatency,
-    RoutineType.kLanConnectivity,
+export function getRoutineGroups(type, isArcEnabled) {
+  let localNetworkGroup = new RoutineGroup(
+      [
+        RoutineType.kGatewayCanBePinged,
+        RoutineType.kLanConnectivity,
+      ],
+      'localNetworkGroupLabel');
+
+  let nameResolutionGroup = new RoutineGroup(
+      [
+        RoutineType.kDnsResolverPresent,
+        RoutineType.kDnsResolution,
+        RoutineType.kDnsLatency,
+      ],
+      'nameResolutionGroupLabel');
+
+  let wifiGroup = new RoutineGroup(
+      [
+        RoutineType.kSignalStrength,
+        RoutineType.kCaptivePortal,
+        RoutineType.kHasSecureWiFiConnection,
+      ],
+      'wifiGroupLabel');
+  let internetConnectivityGroup = new RoutineGroup(
+      [
+        RoutineType.kHttpsFirewall,
+        RoutineType.kHttpFirewall,
+        RoutineType.kHttpsLatency,
+      ],
+      'internetConnectivityGroupLabel');
+
+  if (isArcEnabled) {
+    // Add ARC routines to their corresponding groups.
+    nameResolutionGroup.routines.push(RoutineType.kArcDnsResolution);
+    internetConnectivityGroup.routines.push(RoutineType.kArcPing);
+    internetConnectivityGroup.routines.push(RoutineType.kArcHttp);
+  }
+
+  let groupsToAdd = type === NetworkType.kWiFi ?
+      [wifiGroup, internetConnectivityGroup] :
+      [internetConnectivityGroup];
+
+  let networkRoutineGroups = [
+    localNetworkGroup,
+    nameResolutionGroup,
   ];
 
-  if (loadTimeData.getBoolean('enableArcNetworkDiagnostics')) {
-    networkRoutines = networkRoutines.concat([
-      RoutineType.kArcHttp,
-      RoutineType.kArcPing,
-      RoutineType.kArcDnsResolution
-    ]);
-  }
-
-  // Add wifi-only routines to common networking routine array.
-  if (type === NetworkType.kWiFi) {
-    networkRoutines.push(RoutineType.kHasSecureWiFiConnection);
-    networkRoutines.push(RoutineType.kSignalStrength);
-  }
-
-  return networkRoutines;
+  return networkRoutineGroups.concat(groupsToAdd);
 }
 
 /**
diff --git a/ash/webui/diagnostics_ui/resources/fake_data.js b/ash/webui/diagnostics_ui/resources/fake_data.js
index 7d75848..3e5c9e29 100644
--- a/ash/webui/diagnostics_ui/resources/fake_data.js
+++ b/ash/webui/diagnostics_ui/resources/fake_data.js
@@ -431,6 +431,30 @@
 };
 
 /** @type {!Network} */
+export let fakePortalWifiNetwork = {
+  state: NetworkState.kPortal,
+  type: NetworkType.kWiFi,
+  typeProperties: {
+    wifi: {
+      signalStrength: 65,
+      frequency: 5745,
+      bssid: '44:07:0b:06:2d:85',
+      ssid: 'Dial Up',
+      security: SecurityType.kWepPsk,
+    },
+  },
+  observerGuid: 'wifiPortalGuid',
+  name: '',
+  macAddress: '84:C5:A6:30:3F:31',
+  ipConfig: {
+    ipAddress: '192.168.86.197',
+    gateway: '192.168.86.1',
+    nameServers: ['192.168.86.1', '192.168.86.2'],
+    routingPrefix: 24,
+  },
+};
+
+/** @type {!Network} */
 export let fakeEthernetNetwork = {
   state: NetworkState.kOnline,
   type: NetworkType.kEthernet,
diff --git a/ash/webui/diagnostics_ui/resources/network_card.html b/ash/webui/diagnostics_ui/resources/network_card.html
index bb8193e..d31552d 100644
--- a/ash/webui/diagnostics_ui/resources/network_card.html
+++ b/ash/webui/diagnostics_ui/resources/network_card.html
@@ -1,6 +1,7 @@
 <style include="diagnostics-shared diagnostics-fonts">
 </style>
-<diagnostics-card is-networking-card>
+<diagnostics-card is-networking-card
+    hide-data-points="[[!showNetworkDataPoints_]]">
     <!-- TODO(michaelcheco): Add localized strings. -->
   <template is="dom-if" if="[[showTroubleConnectingState_]]">
     <network-troubleshooting id="networkTroubleshooting"
@@ -12,9 +13,11 @@
   <div id="cardTitle" slot="title">
     [[getNetworkCardTitle_(networkType_, networkState_, macAddress_)]]
   </div>
-  <network-info slot="body" guid="[[guid]]" network="[[network]]">
-  </network-info>
-  <ip-config-info-drawer id="ipConfigInfoDrawer" network="[[network]]"
-      slot="routines">
-  </ip-config-info-drawer>
+  <template is="dom-if" if="[[showNetworkDataPoints_]]">
+    <network-info slot="body" guid="[[guid]]" network="[[network]]">
+    </network-info>
+    <ip-config-info-drawer id="ipConfigInfoDrawer" network="[[network]]"
+        slot="routines">
+    </ip-config-info-drawer>
+  </template>
 </diagnostics-card>
diff --git a/ash/webui/diagnostics_ui/resources/network_card.js b/ash/webui/diagnostics_ui/resources/network_card.js
index 987772fe..fde969881 100644
--- a/ash/webui/diagnostics_ui/resources/network_card.js
+++ b/ash/webui/diagnostics_ui/resources/network_card.js
@@ -63,6 +63,12 @@
     },
 
     /** @protected {boolean} */
+    showNetworkDataPoints_: {
+      type: Boolean,
+      computed: 'computeShouldShowNetworkDataPoints_(network.state)',
+    },
+
+    /** @protected {boolean} */
     showTroubleConnectingState_: {
       type: Boolean,
       computed: 'computeShouldShowTroubleConnecting_(network.state)',
@@ -129,6 +135,27 @@
     return `${this.networkType_} [${this.macAddress_}] (${this.networkState_})`;
   },
 
+  /**
+   * @protected
+   * @return {boolean}
+   */
+  computeShouldShowNetworkDataPoints_() {
+    // Wait until the network is present before deciding.
+    if (!this.network) {
+      return false;
+    }
+
+    // Show the data-points when portal, online, or connected.
+    switch (this.network.state) {
+      case NetworkState.kPortal:
+      case NetworkState.kOnline:
+      case NetworkState.kConnected:
+        return true;
+      default:
+        return false;
+    }
+  },
+
   /** @protected */
   computeShouldShowTroubleConnecting_() {
     // Wait until the network is present before deciding.
diff --git a/ash/webui/diagnostics_ui/resources/routine_group.js b/ash/webui/diagnostics_ui/resources/routine_group.js
new file mode 100644
index 0000000..1ce81eca
--- /dev/null
+++ b/ash/webui/diagnostics_ui/resources/routine_group.js
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {RoutineType, StandardRoutineResult} from './diagnostics_types.js';
+import {ExecutionProgress, ResultStatusItem} from './routine_list_executor.js';
+import {getRoutineType, getSimpleResult} from './routine_result_entry.js';
+
+/**
+ * @fileoverview
+ * Used to aggregate individual tests into a shared category (Wi-Fi).
+ */
+export class RoutineGroup {
+  /**
+   * @param {!Array<!RoutineType>} routines
+   * @param {string} groupName
+   */
+  constructor(routines, groupName) {
+    /** @type {!Array<!RoutineType>} */
+    this.routines = routines;
+    /** @type {string} */
+    this.groupName = groupName;
+    /** @type {!ExecutionProgress} */
+    this.progress = ExecutionProgress.kNotStarted;
+
+    /**
+     * Used to track the first test failure in the group of tests.
+     * @type {?string}
+     */
+    this.failedTest = null;
+  }
+
+  /**
+   * Determine overall status of routine group. Report test status as "running"
+   * as long as the current routine is not the last routine in the group.
+   * @param {!ResultStatusItem} status
+   */
+  setStatus(status) {
+    if (status.progress !== ExecutionProgress.kCompleted) {
+      this.progress = status.progress;
+      return;
+    }
+
+    const isLastRoutine =
+        status.routine === this.routines[this.routines.length - 1];
+
+    // Only set status to "completed" if all routines in this group
+    // are finished running.
+    this.progress = isLastRoutine ? ExecutionProgress.kCompleted :
+                                    ExecutionProgress.kRunning;
+
+    const testFailed =
+        getSimpleResult(/** @type {!ResultStatusItem} */ (status.result)) !==
+        StandardRoutineResult.kTestPassed;
+    if (status.result && testFailed) {
+      this.failedTest = this.failedTest || getRoutineType(status.routine);
+    }
+  }
+
+  /**
+   * Clones properties of RoutineGroup and returns new RoutineGroup
+   * @return {!RoutineGroup}
+   */
+  clone() {
+    const clonedRoutineGroup = new RoutineGroup(this.routines, this.groupName);
+    clonedRoutineGroup.progress = this.progress;
+    clonedRoutineGroup.failedTest = this.failedTest;
+    return clonedRoutineGroup;
+  }
+}
\ No newline at end of file
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_entry.html b/ash/webui/diagnostics_ui/resources/routine_result_entry.html
index fdaeac10..6461e5e 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_entry.html
+++ b/ash/webui/diagnostics_ui/resources/routine_result_entry.html
@@ -127,5 +127,8 @@
         <iron-icon icon="cr:open-in-new"></iron-icon>
       </a>
     </span>
+    <span class="routineLinkContainer" hidden$="[[!item.failedTest]]">
+      [[computeFailedTestText_(item.failedTest)]]
+    </span>
   </div>
 </div>
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_entry.js b/ash/webui/diagnostics_ui/resources/routine_result_entry.js
index 439a575..c3e8b44e 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_entry.js
+++ b/ash/webui/diagnostics_ui/resources/routine_result_entry.js
@@ -12,6 +12,7 @@
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {RoutineResult, RoutineType, StandardRoutineResult} from './diagnostics_types.js';
+import {RoutineGroup} from './routine_group.js';
 import {ExecutionProgress, ResultStatusItem} from './routine_list_executor.js';
 import {BadgeType} from './text_badge.js';
 
@@ -128,7 +129,7 @@
 
 /**
  * @fileoverview
- * 'routine-result-entry' shows the status of a single test routine.
+ * 'routine-result-entry' shows the status of a single test routine or group.
  */
 Polymer({
   is: 'routine-result-entry',
@@ -136,7 +137,7 @@
   _template: html`{__html_template__}`,
 
   properties: {
-    /** @type {!ResultStatusItem} */
+    /** @type {RoutineGroup|ResultStatusItem} */
     item: {
       type: Object,
     },
@@ -144,13 +145,13 @@
     /** @private */
     routineType_: {
       type: String,
-      computed: 'getRunningRoutineString_(item.routine)',
+      computed: 'getRunningRoutineString_(item.*)',
     },
 
     /** @protected */
     routineLink_: {
       type: String,
-      computed: 'getRoutineLink_(item.routine)',
+      computed: 'getRoutineLink_(item.*)',
     },
 
     /** @protected {!BadgeType} */
@@ -176,9 +177,15 @@
       type: Boolean,
       value: false,
     },
+
+    /** @type {boolean} */
+    usingRoutineGroups: {
+      type: Boolean,
+      value: false,
+    },
   },
 
-  observers: ['entryStatusChanged_(item.progress, item.result)'],
+  observers: ['entryStatusChanged_(item.*)'],
 
   /** @override */
   attached() {
@@ -187,21 +194,25 @@
 
   /**
    * Get the localized string name for the routine.
-   * @param {!RoutineType} routine
    * @return {string}
    */
-  getRunningRoutineString_(routine) {
-    return loadTimeData.getStringF('routineEntryText', getRoutineType(routine));
+  getRunningRoutineString_() {
+    if (this.usingRoutineGroups) {
+      return loadTimeData.getString(this.item.groupName);
+    }
+
+    return loadTimeData.getStringF(
+        'routineEntryText', getRoutineType(this.item.routine));
   },
 
   /**
    * Get routine's help/info link from lookup function
-   * @param {!RoutineType} routine
    * @return {string}
    * @private
    */
-  getRoutineLink_(routine) {
-    return lookupLinkForRoutine(routine);
+  getRoutineLink_() {
+    // TODO(michaelcheco): Use |lookupLinkForRoutine| to get correct links.
+    return this.usingRoutineGroups ? '#' : '';
   },
 
   /**
@@ -225,9 +236,11 @@
         break;
       case ExecutionProgress.kCompleted:
         this.testCompleted_ = true;
-        const testPassed = this.item.result &&
-            getSimpleResult(this.item.result) ===
-                StandardRoutineResult.kTestPassed;
+        const testPassed = this.usingRoutineGroups ?
+            !this.item.failedTest :
+            (this.item.result &&
+             getSimpleResult(this.item.result) ===
+                 StandardRoutineResult.kTestPassed);
         const badgeType = testPassed ? BadgeType.SUCCESS : BadgeType.ERROR;
         const badgeText = loadTimeData.getString(
             testPassed ? 'testSucceededBadgeText' : 'testFailedBadgeText');
@@ -289,4 +302,16 @@
   shouldHideLines_() {
     return this.hideVerticalLines || !this.testCompleted_;
   },
+
+  /**
+   * @protected
+   * @return {string}
+   */
+  computeFailedTestText_() {
+    if (!this.usingRoutineGroups || !this.item.failedTest) {
+      return '';
+    }
+
+    return loadTimeData.getStringF('routineFailedText', this.item.failedTest);
+  },
 });
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_list.html b/ash/webui/diagnostics_ui/resources/routine_result_list.html
index ac77ad5a..da71bd6a 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_list.html
+++ b/ash/webui/diagnostics_ui/resources/routine_result_list.html
@@ -4,7 +4,8 @@
   <dom-repeat id="resultList" items="[[results_]]">
     <template>
       <routine-result-entry item="[[item]]"
-          hide-vertical-lines="[[shouldHideVerticalLines_(item)]]">
+          hide-vertical-lines="[[shouldHideVerticalLines_(item.*)]]"
+          using-routine-groups="[[usingRoutineGroups]]">
       </routine-result-entry>
     </template>
   </dom-repeat>
diff --git a/ash/webui/diagnostics_ui/resources/routine_result_list.js b/ash/webui/diagnostics_ui/resources/routine_result_list.js
index 86a932b..8da5bc8 100644
--- a/ash/webui/diagnostics_ui/resources/routine_result_list.js
+++ b/ash/webui/diagnostics_ui/resources/routine_result_list.js
@@ -9,7 +9,8 @@
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {RoutineType} from './diagnostics_types.js';
-import {ExecutionProgress, ResultStatusItem} from './routine_list_executor.js'
+import {RoutineGroup} from './routine_group.js';
+import {ResultStatusItem} from './routine_list_executor.js'
 
 /**
  * @fileoverview
@@ -21,7 +22,7 @@
   _template: html`{__html_template__}`,
 
   properties: {
-    /** @private {!Array<!ResultStatusItem>} */
+    /** @private {!Array<RoutineGroup|ResultStatusItem>} */
     results_: {
       type: Array,
       value: () => [],
@@ -38,19 +39,27 @@
       type: Boolean,
       value: false,
     },
+
+    /** @type {boolean} */
+    usingRoutineGroups: {
+      type: Boolean,
+      value: false,
+    },
   },
 
   /**
    * Resets the list and creates a new list with all routines in the unstarted
    * state. Called by the parent RoutineResultSection when the user starts
    * a test run.
-   * @param {!Array<!RoutineType>} routines
+   * @param {!Array<RoutineGroup|RoutineType>} routines
    */
   initializeTestRun(routines) {
     this.clearRoutines();
-    routines.forEach((routine) => {
-      this.addRoutine_(routine);
-    });
+    if (this.usingRoutineGroups) {
+      this.set('results_', routines);
+    } else {
+      this.addRoutines_(routines);
+    }
   },
 
   /**
@@ -61,18 +70,19 @@
   },
 
   /**
-   * Add a new unstarted routine to the end of the list.
-   * @param {!RoutineType} routine
-   * @private
+   * Creates a list of unstarted routines.
+   * @param {!Array<!RoutineType>} routines
    */
-  addRoutine_(routine) {
-    this.push('results_', new ResultStatusItem(routine));
+  addRoutines_(routines) {
+    for (let routine of routines) {
+      this.push('results_', new ResultStatusItem(routine));
+    }
   },
 
   /**
    * Updates the routine's status in the results_ list.
    * @param {number} index
-   * @param {!ResultStatusItem} status
+   * @param {RoutineGroup|ResultStatusItem} status
    * @private
    */
   updateRoutineStatus_(index, status) {
@@ -87,22 +97,28 @@
    */
   onStatusUpdate(status) {
     assert(this.results_.length > 0);
-    this.results_.forEach((result, index) => {
-      if (result.routine == status.routine) {
-        this.updateRoutineStatus_(index, status);
+    this.results_.forEach((result, idx) => {
+      if (this.usingRoutineGroups && result.routines.includes(status.routine)) {
+        result.setStatus(status);
+        this.updateRoutineStatus_(idx, result.clone());
         return;
       }
-    });
+
+      if (status.routine === result.routine) {
+        this.updateRoutineStatus_(idx, status);
+        return;
+      }
+    })
   },
 
   /**
    * @protected
-   * @param {!ResultStatusItem} item
+   * @param {{path: string, value: (RoutineGroup|ResultStatusItem)}} item
    * @return {boolean}
    */
-  shouldHideVerticalLines_(item) {
+  shouldHideVerticalLines_({value}) {
     return this.hideVerticalLines ||
-        item === this.results_[this.results_.length - 1];
+        value === this.results_[this.results_.length - 1];
   },
 
   /** @override */
diff --git a/ash/webui/diagnostics_ui/resources/routine_section.html b/ash/webui/diagnostics_ui/resources/routine_section.html
index 0379260..b8df796 100644
--- a/ash/webui/diagnostics_ui/resources/routine_section.html
+++ b/ash/webui/diagnostics_ui/resources/routine_section.html
@@ -102,7 +102,8 @@
   <iron-collapse id="collapse" opened="{{opened}}">
     <div class="result-list">
       <routine-result-list id="resultList"
-          hide-vertical-lines="[[hideVerticalLines]]">
+          hide-vertical-lines="[[hideVerticalLines]]"
+          using-routine-groups="[[usingRoutineGroups]]">
       </routine-result-list>
     </div>
     <cr-button id="learnMoreButton" class="learn-more-button"
diff --git a/ash/webui/diagnostics_ui/resources/routine_section.js b/ash/webui/diagnostics_ui/resources/routine_section.js
index 87a857b..7dfa98a1 100644
--- a/ash/webui/diagnostics_ui/resources/routine_section.js
+++ b/ash/webui/diagnostics_ui/resources/routine_section.js
@@ -19,7 +19,8 @@
 
 import {PowerRoutineResult, RoutineType, StandardRoutineResult, SystemRoutineControllerInterface} from './diagnostics_types.js';
 import {getSystemRoutineController} from './mojo_interface_provider.js';
-import {ExecutionProgress, RoutineListExecutor, TestSuiteStatus} from './routine_list_executor.js';
+import {RoutineGroup} from './routine_group.js';
+import {ExecutionProgress, ResultStatusItem, RoutineListExecutor, TestSuiteStatus} from './routine_list_executor.js';
 import {getRoutineType, getSimpleResult} from './routine_result_entry.js';
 import {BadgeType} from './text_badge.js';
 
@@ -43,16 +44,16 @@
 
   /**
    * Boolean whether last run had at least one failure,
-   * @type {boolean}
+   * @type {?RoutineType}
    * @private
    */
-  hasTestFailure_: false,
+  failedTest_: null,
 
   /** @private {?SystemRoutineControllerInterface} */
   systemRoutineController_: null,
 
   properties: {
-    /** @type {!Array<!RoutineType>} */
+    /** @type {!Array<RoutineGroup|RoutineType>} */
     routines: {
       type: Array,
       value: () => [],
@@ -195,6 +196,13 @@
       type: Boolean,
       value: false,
     },
+
+    /** @type {boolean} */
+    usingRoutineGroups: {
+      type: Boolean,
+      value: false,
+      computed: 'getUsingRoutineGroupsVal_(routines.*)',
+    },
   },
 
   observers: [
@@ -212,92 +220,156 @@
     return this.initialButtonText_ || buttonText;
   },
 
+  /**
+   * @return {boolean}
+   * @private
+   */
+  getUsingRoutineGroupsVal_() {
+    if (this.routines.length === 0) {
+      return false;
+    }
+    return this.routines[0] instanceof RoutineGroup;
+  },
+
   /** @private */
   getResultListElem_() {
     return /** @type {!RoutineResultListElement} */ (
         this.$$('routine-result-list'));
   },
 
-  runTests() {
+
+  /**
+   *  @private
+   *  @return {!Promise<!Array<!RoutineType>>}
+   */
+  async getSupportedRoutines_() {
+    const supported =
+        await this.systemRoutineController_.getSupportedRoutines();
+    const filteredRoutineTypes = this.routines.filter(
+        routine =>
+            supported.routines.includes(/** @type {!RoutineType} */ (routine)));
+    return filteredRoutineTypes;
+  },
+
+  /**
+   *  @private
+   *  @return {!Promise<!Array<!RoutineGroup>>}
+   */
+  async getSupportedRoutineGroups_() {
+    const supported =
+        await this.systemRoutineController_.getSupportedRoutines();
+    const filteredRoutineGroups = [];
+    for (const routineGroup of this.routines) {
+      routineGroup.routines = routineGroup.routines.filter(
+          routine => supported.routines.includes(routine));
+      if (routineGroup.routines.length > 0) {
+        filteredRoutineGroups.push(routineGroup.clone());
+      }
+    }
+    return filteredRoutineGroups;
+  },
+
+  async runTests() {
     // Do not attempt to run tests when no routines available to run.
     if (this.routines.length === 0) {
       return;
     }
     this.testSuiteStatus = TestSuiteStatus.kRunning;
-    this.hasTestFailure_ = false;
+    this.failedTest_ = null;
 
     this.systemRoutineController_ = getSystemRoutineController();
     const resultListElem = this.getResultListElem_();
-    this.systemRoutineController_.getSupportedRoutines().then((supported) => {
-      const filteredRoutines =
-          this.routines.filter(routine => supported.routines.includes(routine));
+    const routines = this.usingRoutineGroups ?
+        await this.getSupportedRoutineGroups_() :
+        await this.getSupportedRoutines_();
+    resultListElem.initializeTestRun(routines);
 
-      resultListElem.initializeTestRun(filteredRoutines);
+    // Expand result list by default.
+    if (!this.shouldHideReportList_()) {
+      this.$.collapse.show();
+    }
 
-      // Expand result list by default.
-      if (!this.shouldHideReportList_()) {
-        this.$.collapse.show();
+    if (this.bannerMessage) {
+      this.showCautionBanner_();
+    }
+
+    this.routineStartTimeMs_ = performance.now();
+
+    // Set initial status badge text.
+    this.setRunningStatusBadgeText_();
+
+    const remainingTimeUpdaterId =
+        setInterval(() => this.setRunningStatusBadgeText_(), 1000);
+    const executor =
+        new RoutineListExecutor(assert(this.systemRoutineController_));
+    this.executor_ = executor;
+    if (!this.usingRoutineGroups) {
+      let status = await executor.runRoutines(
+          routines,
+          (routineStatus) =>
+              this.handleRunningRoutineStatus_(routineStatus, resultListElem));
+      this.handleRoutinesCompletedStatus_(status);
+      clearInterval(remainingTimeUpdaterId);
+      return;
+    }
+
+    for (let i = 0; i < routines.length; i++) {
+      const routineGroup = routines[i];
+      const status = await executor.runRoutines(
+          routineGroup.routines,
+          (routineStatus) =>
+              this.handleRunningRoutineStatus_(routineStatus, resultListElem));
+      const isLastRoutineGroup = i === routines.length - 1;
+      if (isLastRoutineGroup) {
+        this.handleRoutinesCompletedStatus_(status);
+        clearInterval(remainingTimeUpdaterId);
       }
+    }
+  },
 
-      if (this.bannerMessage) {
-        this.showCautionBanner_();
-      }
+  /** @param {!ExecutionProgress} status */
+  handleRoutinesCompletedStatus_(status) {
+    this.executionStatus_ = status;
+    this.testSuiteStatus = status === ExecutionProgress.kCancelled ?
+        TestSuiteStatus.kNotRunning :
+        TestSuiteStatus.kCompleted;
+    this.routineStartTimeMs_ = -1;
+    this.runTestsButtonText = loadTimeData.getString('runAgainButtonText');
+    this.cleanUp_();
+    if (status === ExecutionProgress.kCancelled) {
+      this.badgeText_ = loadTimeData.getString('testStoppedBadgeText');
+    } else {
+      this.badgeText_ = this.failedTest_ ?
+          loadTimeData.getString('testFailedBadgeText') :
+          loadTimeData.getString('testSucceededBadgeText');
+    }
+  },
 
-      this.routineStartTimeMs_ = performance.now();
+  /**
+   * @param {!ResultStatusItem} status
+   * @param {!RoutineResultListElement} resultListElem
+   * @private
+   */
+  handleRunningRoutineStatus_(status, resultListElem) {
+    if (status.result && status.result.powerResult) {
+      this.powerRoutineResult_ = status.result.powerResult;
+    }
 
-      // Set initial status badge text.
-      this.setRunningStatusBadgeText_();
+    if (status.result &&
+        getSimpleResult(status.result) !== StandardRoutineResult.kTestPassed &&
+        !this.failedTest_) {
+      this.failedTest_ = status.routine;
+    }
 
-      const remainingTimeUpdaterId =
-          setInterval(() => this.setRunningStatusBadgeText_(), 1000);
+    // Execution progress is checked here to avoid overwriting
+    // the test name shown in the status text.
+    if (status.progress !== ExecutionProgress.kCancelled) {
+      this.currentTestName_ = getRoutineType(status.routine);
+    }
 
-      this.executor_ =
-          new RoutineListExecutor(assert(this.systemRoutineController_));
-      this.executor_
-          .runRoutines(
-              filteredRoutines,
-              (status) => {
-                if (status.result && status.result.powerResult) {
-                  this.powerRoutineResult_ = status.result.powerResult;
-                }
+    this.executionStatus_ = status.progress;
 
-                if (status.result &&
-                    getSimpleResult(status.result) !==
-                        StandardRoutineResult.kTestPassed) {
-                  this.hasTestFailure_ = true;
-                }
-
-                // Execution progress is checked here to avoid overwriting the
-                // test name shown in the status text.
-                if (status.progress !== ExecutionProgress.kCancelled) {
-                  this.currentTestName_ = getRoutineType(status.routine);
-                }
-
-                this.executionStatus_ = status.progress;
-
-                resultListElem.onStatusUpdate.call(resultListElem, status);
-              })
-          .then((/** @type {!ExecutionProgress} */ status) => {
-            this.executionStatus_ = status;
-            this.testSuiteStatus = status === ExecutionProgress.kCancelled ?
-                TestSuiteStatus.kNotRunning :
-                TestSuiteStatus.kCompleted;
-            this.routineStartTimeMs_ = -1;
-            this.runTestsButtonText =
-                loadTimeData.getString('runAgainButtonText');
-            clearInterval(remainingTimeUpdaterId);
-
-            if (status === ExecutionProgress.kCancelled) {
-              this.badgeText_ = loadTimeData.getString('testStoppedBadgeText')
-            } else {
-              this.badgeText_ = this.hasTestFailure_ ?
-                  loadTimeData.getString('testFailedBadgeText') :
-                  loadTimeData.getString('testSucceededBadgeText');
-            }
-
-            this.cleanUp_();
-          });
-    });
+    resultListElem.onStatusUpdate.call(resultListElem, status);
   },
 
   /** @private */
@@ -410,7 +482,7 @@
         break;
       case ExecutionProgress.kCompleted:
         const isPowerRoutine = this.isPowerRoutine || this.powerRoutineResult_;
-        if (this.hasTestFailure_) {
+        if (this.failedTest_) {
           this.setBadgeAndStatusText_(
               BadgeType.ERROR, loadTimeData.getString('testFailure'));
         } else {
@@ -430,6 +502,7 @@
    * @return {string}
    */
   getPowerRoutineString_() {
+    assert(!this.usingRoutineGroups);
     const stringId = this.routines.includes(RoutineType.kBatteryCharge) ?
         'chargeTestResultText' :
         'dischargeTestResultText';
diff --git a/ash/webui/scanning/resources/scan_preview.html b/ash/webui/scanning/resources/scan_preview.html
index e281552..1d1289c5 100644
--- a/ash/webui/scanning/resources/scan_preview.html
+++ b/ash/webui/scanning/resources/scan_preview.html
@@ -60,7 +60,7 @@
     box-shadow: 0 0 0 var(--preview-border-width) rgba(var(--google-blue-600-rgb), .4);
   }
 
-  .preview:hover {
+  :host([show-single-image-focus_]) .preview:hover {
     box-shadow: none;
   }
 
@@ -78,7 +78,7 @@
     width: calc(100% - 24px);
   }
 
-  :host(:not([multi-page-scanning_])) .preview:hover .focused-scanned-image {
+  :host([show-single-image-focus_]) .preview:hover .focused-scanned-image {
     box-shadow: rgba(var(--google-blue-600-rgb), .4) 0 0 0 var(--preview-border-width);
   }
 
diff --git a/ash/webui/scanning/resources/scan_preview.js b/ash/webui/scanning/resources/scan_preview.js
index a06750aa..e4d309f3 100644
--- a/ash/webui/scanning/resources/scan_preview.js
+++ b/ash/webui/scanning/resources/scan_preview.js
@@ -42,6 +42,9 @@
   /** @private {?Function} */
   onWindowResized_: null,
 
+  /** @private {?ResizeObserver} */
+  previewAreaResizeObserver_: null,
+
   /** @private {?Function} */
   onDialogActionClick_: null,
 
@@ -160,6 +163,12 @@
       value: false,
       reflectToAttribute: true,
     },
+
+    /** @private {boolean} */
+    showSingleImageFocus_: {
+      type: Boolean,
+      reflectToAttribute: true,
+    },
   },
 
   observers: [
@@ -172,10 +181,9 @@
   created() {
     // ScanningBrowserProxy is initialized when scanning_app.js is created.
     this.browserProxy_ = ScanningBrowserProxyImpl.getInstance();
-    this.onWindowResized_ = () => {
-      this.setMultiPageScanProgessHeight_();
-      this.setActionToolbarPosition_();
-    };
+    this.onWindowResized_ = () => this.setActionToolbarPosition_();
+    this.previewAreaResizeObserver_ =
+        new ResizeObserver(() => this.setMultiPageScanProgessHeight_());
   },
 
   /** @override */
@@ -188,6 +196,7 @@
   detached() {
     if (this.isMultiPageScan) {
       window.removeEventListener('resize', this.onWindowResized_);
+      this.previewAreaResizeObserver_.disconnect();
     }
   },
 
@@ -205,6 +214,8 @@
     this.showHelpOrProgress_ = !this.showScannedImages_ ||
         this.appState === AppState.MULTI_PAGE_SCANNING;
     this.multiPageScanning_ = this.appState === AppState.MULTI_PAGE_SCANNING;
+    this.showSingleImageFocus_ =
+        this.appState === AppState.MULTI_PAGE_NEXT_ACTION;
 
     // If no longer showing the scanned images, reset |scannedImagesLoaded_| so
     // it can be used again for the next scan job.
@@ -396,8 +407,6 @@
     this.setFocusedScannedImage_(
         scannedImages, this.getCurrentPageInView_(scannedImages));
 
-    this.setMultiPageScanProgessHeight_();
-
     // The below actions only needed for the first scanned image load.
     if (this.scannedImagesLoaded_) {
       return;
@@ -550,12 +559,19 @@
 
   /** @private */
   onIsMultiPageScanChange_() {
-    // Only listen for window size changes during multi-page scan sessions so
-    // the position of the action toolbar can be updated.
+    // Listen for window size changes during multi-page scan sessions so the
+    // position of the action toolbar can be updated.
     if (this.isMultiPageScan) {
       window.addEventListener('resize', this.onWindowResized_);
+
+      // Observe changes to the preview area during multi-page scan sessions so
+      // the scan progress div height can be updated when images are
+      // added/removed.
+      this.previewAreaResizeObserver_.observe(
+          /** @type {!HTMLElement} */ (this.$$('#previewDiv')));
     } else {
       window.removeEventListener('resize', this.onWindowResized_);
+      this.previewAreaResizeObserver_.disconnect();
     }
   },
 
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.cc b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
index 39b3719de..605dbb2d 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service.cc
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service.cc
@@ -536,7 +536,9 @@
   std::move(callback).Run(state_proto_.setup_calibration().instruction());
 }
 
-void ShimlessRmaService::StartCalibration(StartCalibrationCallback callback) {
+void ShimlessRmaService::StartCalibration(
+    const std::vector<::rmad::CalibrationComponentStatus>& components,
+    StartCalibrationCallback callback) {
   if (state_proto_.state_case() != rmad::RmadState::kCheckCalibration) {
     LOG(ERROR) << "StartCalibration called from incorrect state "
                << state_proto_.state_case();
@@ -545,6 +547,18 @@
                             rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID);
     return;
   }
+  state_proto_.mutable_check_calibration()->clear_components();
+  state_proto_.mutable_check_calibration()->mutable_components()->Reserve(
+      components.size());
+  for (auto& component : components) {
+    rmad::CalibrationComponentStatus* proto_component =
+        state_proto_.mutable_check_calibration()->add_components();
+    proto_component->set_component(component.component());
+    // rmad only cares if the status is set to skip or not.
+    proto_component->set_status(component.status());
+    // Progress is not relevant when sending to rmad.
+    proto_component->set_progress(0.0);
+  }
   TransitionNextStateGeneric(std::move(callback));
 }
 
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service.h b/ash/webui/shimless_rma/backend/shimless_rma_service.h
index c559975..c914cc9 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service.h
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service.h
@@ -96,7 +96,9 @@
       GetCalibrationComponentListCallback callback) override;
   void GetCalibrationSetupInstructions(
       GetCalibrationSetupInstructionsCallback callback) override;
-  void StartCalibration(StartCalibrationCallback callback) override;
+  void StartCalibration(
+      const std::vector<::rmad::CalibrationComponentStatus>& components,
+      StartCalibrationCallback callback) override;
   void RunCalibrationStep(RunCalibrationStepCallback callback) override;
   void ContinueCalibration(ContinueCalibrationCallback callback) override;
   void CalibrationComplete(CalibrationCompleteCallback callback) override;
diff --git a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
index 68b3498d..fa3caac 100644
--- a/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
+++ b/ash/webui/shimless_rma/backend/shimless_rma_service_unittest.cc
@@ -1916,6 +1916,23 @@
       CreateStateReply(rmad::RmadState::kDeviceDestination,
                        rmad::RMAD_ERROR_OK)};
   fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states));
+  fake_rmad_client_()->check_state_callback =
+      base::BindRepeating([](const rmad::RmadState& state) {
+        EXPECT_EQ(state.state_case(), rmad::RmadState::kCheckCalibration);
+        EXPECT_EQ(2, state.check_calibration().components_size());
+        EXPECT_EQ(state.check_calibration().components(0).component(),
+                  rmad::RmadComponent::RMAD_COMPONENT_KEYBOARD);
+        EXPECT_EQ(state.check_calibration().components(0).status(),
+                  rmad::CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
+        // Progress passed to rmad should always be zero.
+        EXPECT_EQ(state.check_calibration().components(0).progress(), 0.0);
+        EXPECT_EQ(state.check_calibration().components(1).component(),
+                  rmad::RmadComponent::RMAD_COMPONENT_TOUCHPAD);
+        EXPECT_EQ(state.check_calibration().components(1).status(),
+                  rmad::CalibrationComponentStatus::RMAD_CALIBRATION_SKIP);
+        // Progress passed to rmad should always be zero.
+        EXPECT_EQ(state.check_calibration().components(1).progress(), 0.0);
+      });
   base::RunLoop run_loop;
   shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting(
       [&](mojom::RmaState state, bool can_cancel, bool can_go_back,
@@ -1925,9 +1942,21 @@
       }));
   run_loop.RunUntilIdle();
 
-  shimless_rma_provider_->StartCalibration(base::BindLambdaForTesting(
-      [&](mojom::RmaState state, bool can_cancel, bool can_go_back,
-          rmad::RmadErrorCode error) {
+  std::vector<rmad::CalibrationComponentStatus> components(2);
+  components[0].set_component(rmad::RmadComponent::RMAD_COMPONENT_KEYBOARD);
+  components[0].set_status(
+      rmad::CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
+  components[0].set_progress(0.25);
+  components[1].set_component(rmad::RmadComponent::RMAD_COMPONENT_TOUCHPAD);
+  components[1].set_status(
+      rmad::CalibrationComponentStatus::RMAD_CALIBRATION_SKIP);
+  components[1].set_progress(0.5);
+
+  shimless_rma_provider_->StartCalibration(
+      std::move(components),
+      base::BindLambdaForTesting([&](mojom::RmaState state, bool can_cancel,
+                                     bool can_go_back,
+                                     rmad::RmadErrorCode error) {
         EXPECT_EQ(state, mojom::RmaState::kChooseDestination);
         EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_OK);
         run_loop.Quit();
@@ -1939,6 +1968,8 @@
   std::vector<rmad::GetStateReply> fake_states = {CreateStateReply(
       rmad::RmadState::kDeviceDestination, rmad::RMAD_ERROR_OK)};
   fake_rmad_client_()->SetFakeStateReplies(std::move(fake_states));
+  fake_rmad_client_()->check_state_callback =
+      base::BindRepeating([](const rmad::RmadState& state) { NOTREACHED(); });
   base::RunLoop run_loop;
   shimless_rma_provider_->GetCurrentState(base::BindLambdaForTesting(
       [&](mojom::RmaState state, bool can_cancel, bool can_go_back,
@@ -1948,9 +1979,19 @@
       }));
   run_loop.RunUntilIdle();
 
-  shimless_rma_provider_->StartCalibration(base::BindLambdaForTesting(
-      [&](mojom::RmaState state, bool can_cancel, bool can_go_back,
-          rmad::RmadErrorCode error) {
+  std::vector<rmad::CalibrationComponentStatus> components(2);
+  components[0].set_component(rmad::RmadComponent::RMAD_COMPONENT_KEYBOARD);
+  components[0].set_status(
+      rmad::CalibrationComponentStatus::RMAD_CALIBRATION_WAITING);
+  components[1].set_component(rmad::RmadComponent::RMAD_COMPONENT_TOUCHPAD);
+  components[1].set_status(
+      rmad::CalibrationComponentStatus::RMAD_CALIBRATION_SKIP);
+
+  shimless_rma_provider_->StartCalibration(
+      std::move(components),
+      base::BindLambdaForTesting([&](mojom::RmaState state, bool can_cancel,
+                                     bool can_go_back,
+                                     rmad::RmadErrorCode error) {
         EXPECT_EQ(state, mojom::RmaState::kChooseDestination);
         EXPECT_EQ(error, rmad::RmadErrorCode::RMAD_ERROR_REQUEST_INVALID);
         run_loop.Quit();
@@ -1958,7 +1999,6 @@
   run_loop.Run();
 }
 
-// RunCalibrationStep() => (RmaState state, RmadErrorCode error);
 TEST_F(ShimlessRmaServiceTest, RunCalibrationStep) {
   std::vector<rmad::GetStateReply> fake_states = {
       CreateStateReply(rmad::RmadState::kSetupCalibration, rmad::RMAD_ERROR_OK),
@@ -2006,7 +2046,6 @@
       }));
   run_loop.Run();
 }
-// ContinueCalibration() => (RmaState state, RmadErrorCode error);
 TEST_F(ShimlessRmaServiceTest, ContinueCalibration) {
   std::vector<rmad::GetStateReply> fake_states = {
       CreateStateReply(rmad::RmadState::kRunCalibration, rmad::RMAD_ERROR_OK),
@@ -2055,7 +2094,6 @@
   run_loop.Run();
 }
 
-// CalibrationComplete() => (RmaState state, RmadErrorCode error);
 TEST_F(ShimlessRmaServiceTest, CalibrationComplete) {
   std::vector<rmad::GetStateReply> fake_states = {
       CreateStateReply(rmad::RmadState::kRunCalibration, rmad::RMAD_ERROR_OK),
@@ -2277,14 +2315,10 @@
 };
 
 TEST_F(ShimlessRmaServiceTest, NoErrorObserver) {
-  // FakeErrorObserver fake_observer;
-  // shimless_rma_provider_->ObserveError(
-  //     fake_observer.receiver.BindNewPipeAndPassRemote());
   base::RunLoop run_loop;
   fake_rmad_client_()->TriggerErrorObservation(
       rmad::RmadErrorCode::RMAD_ERROR_REIMAGING_UNKNOWN_FAILURE);
   run_loop.RunUntilIdle();
-  // EXPECT_EQ(fake_observer.observations.size(), 1UL);
 }
 
 TEST_F(ShimlessRmaServiceTest, ObserveError) {
diff --git a/ash/webui/shimless_rma/mojom/shimless_rma.mojom b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
index 1ef14c9..273316c 100644
--- a/ash/webui/shimless_rma/mojom/shimless_rma.mojom
+++ b/ash/webui/shimless_rma/mojom/shimless_rma.mojom
@@ -558,7 +558,7 @@
   // Request transition to the begin calibration.
   // Next state will be kSetupCalibration if setup is required, or
   // kRunCalibration if not.
-  StartCalibration()
+  StartCalibration(array<CalibrationComponentStatus> components)
       => (RmaState state, bool can_cancel, bool can_go_back,
           RmadErrorCode error);
   // Request transition from kSetupCalibration to run this calibration step.
diff --git a/ash/webui/shimless_rma/resources/BUILD.gn b/ash/webui/shimless_rma/resources/BUILD.gn
index 300befacb..003e74c8 100644
--- a/ash/webui/shimless_rma/resources/BUILD.gn
+++ b/ash/webui/shimless_rma/resources/BUILD.gn
@@ -14,6 +14,7 @@
 
 polymer_element_files = [
   "base_page.js",
+  "calibration_component_chip.js",
   "icons.js",
   "onboarding_choose_destination_page.js",
   "onboarding_choose_wp_disable_method_page.js",
@@ -40,6 +41,7 @@
 generate_grd("build_grd") {
   input_files = [
     "app_icon_192.png",
+    "data.js",
     "fake_data.js",
     "fake_shimless_rma_service.js",
     "index.html",
@@ -65,6 +67,7 @@
   closure_flags = default_closure_args
   deps = [
     ":base_page",
+    ":calibration_component_chip",
     ":fake_shimless_rma_service",
     ":mojo_interface_provider",
     ":onboarding_choose_destination_page",
@@ -125,6 +128,13 @@
   ]
 }
 
+js_library("data") {
+  deps = [
+    ":shimless_rma_types",
+    "//ui/webui/resources/cr_components/chromeos/network:onc_mojo.m",
+  ]
+}
+
 js_library("fake_data") {
   deps = [
     ":shimless_rma_types",
@@ -194,6 +204,7 @@
 js_library("onboarding_select_components_page") {
   deps = [
     ":base_page",
+    ":data",
     ":mojo_interface_provider",
     ":repair_component_chip",
     ":shimless_rma_types",
@@ -260,6 +271,8 @@
 js_library("reimaging_calibration_page") {
   deps = [
     ":base_page",
+    ":calibration_component_chip",
+    ":data",
     ":icons",
     ":mojo_interface_provider",
     ":shimless_rma_types",
@@ -308,6 +321,12 @@
   ]
 }
 
+js_library("calibration_component_chip") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
 js_library("repair_component_chip") {
   deps = [
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
diff --git a/ash/webui/shimless_rma/resources/calibration_component_chip.html b/ash/webui/shimless_rma/resources/calibration_component_chip.html
new file mode 100644
index 0000000..b52e653c
--- /dev/null
+++ b/ash/webui/shimless_rma/resources/calibration_component_chip.html
@@ -0,0 +1,50 @@
+<style include="cr-shared-style shimless-rma-shared">
+  :host {
+    padding: 1px;
+  }
+
+  /* TODO(gavindodd): update colors to CrOS */
+  :host([skip]) #containerButton {
+    background-color: lightgray;
+  }
+
+  :host([completed]) #containerButton {
+    background-color: yellowgreen;
+  }
+
+  :host([failed]) #containerButton {
+    background-color: IndianRed;
+  }
+
+  #containerDiv {
+    height: 40px;
+    width: 180px;
+  }
+
+  #containerButton {
+    border-radius: 10px;
+    box-shadow: 0px 2px 2px 2px #bbb;
+    height: 40px;
+    width: 180px;
+  }
+
+  .icon-top-right {
+    height: 15px;
+    position: relative;
+    right: 20px;
+    top: -5px;
+    width: 15px;
+  }
+</style>
+
+<div id="containerDiv">
+  <cr-button disabled$="[[disabled]]"
+      id="containerButton" on-click="onComponentButtonClicked_">
+    <span id="componentName">[[componentName]]</span>
+  </cr-button>
+
+  <!-- TODO(gavindodd): Replace icon with checked icon -->
+  <iron-icon id="skipIcon" icon="shimless-icon:wifi"
+    hidden$="[[!skip]]" class="icon-top-right">
+  </iron-icon>
+</div>
diff --git a/ash/webui/shimless_rma/resources/calibration_component_chip.js b/ash/webui/shimless_rma/resources/calibration_component_chip.js
new file mode 100644
index 0000000..ce22d28a
--- /dev/null
+++ b/ash/webui/shimless_rma/resources/calibration_component_chip.js
@@ -0,0 +1,81 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import './shimless_rma_shared_css.js';
+import './icons.js';
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/icons.m.js';
+import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
+import 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js';
+
+import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+/**
+ * @fileoverview
+ * 'calibration-component-chip' represents a single component chip that reports
+ * status of last calibration attempt and can be marked to skip.
+ */
+
+export class CalibrationComponentChipElement extends PolymerElement {
+  static get is() {
+    return 'calibration-component-chip';
+  }
+
+  static get template() {
+    return html`{__html_template__}`;
+  }
+
+  static get properties() {
+    return {
+      /** @type {boolean} */
+      disabled: {
+        type: Boolean,
+        value: false,
+      },
+
+      /** @type {boolean} */
+      skip: {
+        notify: true,
+        reflectToAttribute: true,
+        type: Boolean,
+        value: false,
+      },
+
+      /** @type {boolean} */
+      completed: {
+        notify: true,
+        reflectToAttribute: true,
+        type: Boolean,
+        value: false,
+      },
+
+      /** @type {boolean} */
+      failed: {
+        notify: true,
+        reflectToAttribute: true,
+        type: Boolean,
+        value: false,
+      },
+
+      /** @type {string} */
+      componentName: {type: String, value: ''},
+
+      /** @type {string} */
+      componentStatus: {type: String, value: ''}
+    };
+  }
+
+  /** @protected */
+  onComponentButtonClicked_() {
+    this.skip = !this.skip;
+  }
+
+  click() {
+    this.onComponentButtonClicked_();
+  }
+};
+
+customElements.define(
+    CalibrationComponentChipElement.is, CalibrationComponentChipElement);
diff --git a/ash/webui/shimless_rma/resources/data.js b/ash/webui/shimless_rma/resources/data.js
new file mode 100644
index 0000000..2999933
--- /dev/null
+++ b/ash/webui/shimless_rma/resources/data.js
@@ -0,0 +1,58 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {ComponentType} from './shimless_rma_types.js';
+
+// TODO(gavindodd): i18n strings
+/**
+ * @type {!Object<!ComponentType, string>}
+ */
+export const ComponentTypeToName = {
+  [ComponentType.kAudioCodec]: 'Audio',
+  [ComponentType.kBattery]: 'Battery',
+  [ComponentType.kStorage]: 'Storage',
+  [ComponentType.kVpdCached]: 'Vpd Cached',
+  [ComponentType.kNetwork]: 'Network',
+  [ComponentType.kCamera]: 'Camera',
+  [ComponentType.kStylus]: 'Stylus',
+  [ComponentType.kTouchpad]: 'Touchpad',
+  [ComponentType.kTouchsreen]: 'Touchscreen',
+  [ComponentType.kDram]: 'Memory',
+  [ComponentType.kDisplayPanel]: 'Display',
+  [ComponentType.kCellular]: 'Cellular',
+  [ComponentType.kEthernet]: 'Ethernet',
+  [ComponentType.kWireless]: 'Wireless',
+  [ComponentType.kGyroscope]: 'Gyroscope',
+  [ComponentType.kBaseAccelerometer]: 'Base Accelerometer',
+  [ComponentType.kLidAccelerometer]: 'Lid Accelerometer',
+  [ComponentType.kScreen]: 'Screen',
+  [ComponentType.kKeyboard]: 'Keyboard',
+  [ComponentType.kPowerButton]: 'Power Button'
+};
+
+/**
+ * @type {!Object<!ComponentType, string>}
+ */
+export const ComponentTypeToId = {
+  [ComponentType.kAudioCodec]: 'componentAudio',
+  [ComponentType.kBattery]: 'componentBattery',
+  [ComponentType.kStorage]: 'componentStorage',
+  [ComponentType.kVpdCached]: 'componentVpd Cached',
+  [ComponentType.kNetwork]: 'componentNetwork',
+  [ComponentType.kCamera]: 'componentCamera',
+  [ComponentType.kStylus]: 'componentStylus',
+  [ComponentType.kTouchpad]: 'componentTouchpad',
+  [ComponentType.kTouchsreen]: 'componentTouchscreen',
+  [ComponentType.kDram]: 'componentDram',
+  [ComponentType.kDisplayPanel]: 'componentDisplayPanel',
+  [ComponentType.kCellular]: 'componentCellular',
+  [ComponentType.kEthernet]: 'componentEthernet',
+  [ComponentType.kWireless]: 'componentWireless',
+  [ComponentType.kGyroscope]: 'componentGyroscope',
+  [ComponentType.kBaseAccelerometer]: 'componentBaseAccelerometer',
+  [ComponentType.kLidAccelerometer]: 'componentLidAccelerometer',
+  [ComponentType.kScreen]: 'componentScreen',
+  [ComponentType.kKeyboard]: 'componentKeyboard',
+  [ComponentType.kPowerButton]: 'componentPowerButton'
+};
diff --git a/ash/webui/shimless_rma/resources/fake_data.js b/ash/webui/shimless_rma/resources/fake_data.js
index 4e9c46b..f8a61c9 100644
--- a/ash/webui/shimless_rma/resources/fake_data.js
+++ b/ash/webui/shimless_rma/resources/fake_data.js
@@ -4,7 +4,7 @@
 
 import {OncMojo} from 'chrome://resources/cr_components/chromeos/network/onc_mojo.m.js';
 
-import {Component, ComponentRepairStatus, ComponentType, Network, QrCode, RmadErrorCode, RmaState, StateResult} from './shimless_rma_types.js';
+import {CalibrationComponentStatus, CalibrationStatus, Component, ComponentRepairStatus, ComponentType, Network, QrCode, RmadErrorCode, RmaState, StateResult} from './shimless_rma_types.js';
 
 /** @type {!Array<!StateResult>} */
 export const fakeStates = [
@@ -145,6 +145,35 @@
   {component: ComponentType.kTouchpad, state: ComponentRepairStatus.kReplaced},
 ];
 
+/** @type {!Array<!CalibrationComponentStatus>} */
+export const fakeCalibrationComponents = [
+  {
+    component: ComponentType.kCamera,
+    status: CalibrationStatus.kCalibrationWaiting,
+    progress: 0.0
+  },
+  {
+    component: ComponentType.kBattery,
+    status: CalibrationStatus.kCalibrationComplete,
+    progress: 1.0
+  },
+  {
+    component: ComponentType.kBaseAccelerometer,
+    status: CalibrationStatus.kCalibrationInProgress,
+    progress: 1.0
+  },
+  {
+    component: ComponentType.kLidAccelerometer,
+    status: CalibrationStatus.kCalibrationFailed,
+    progress: 1.0
+  },
+  {
+    component: ComponentType.kTouchpad,
+    status: CalibrationStatus.kCalibrationSkip,
+    progress: 0.0
+  },
+];
+
 /** @type {!Array<!Network>} */
 export const fakeNetworks = [
   OncMojo.getDefaultNetworkState(
diff --git a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
index 45eb9077..857b29f5 100644
--- a/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
+++ b/ash/webui/shimless_rma/resources/fake_shimless_rma_service.js
@@ -550,9 +550,12 @@
   }
 
   /**
+   * The fake does not use the status list parameter, the fake data is never
+   * updated.
+   * @param {!Array<!CalibrationComponentStatus>} unused
    * @return {!Promise<!StateResult>}
    */
-  startCalibration() {
+  startCalibration(unused) {
     return this.getNextStateForMethod_(
         'startCalibration', RmaState.kCheckCalibration);
   }
diff --git a/ash/webui/shimless_rma/resources/mojo_interface_provider.js b/ash/webui/shimless_rma/resources/mojo_interface_provider.js
index 53620ec..4d06470d 100644
--- a/ash/webui/shimless_rma/resources/mojo_interface_provider.js
+++ b/ash/webui/shimless_rma/resources/mojo_interface_provider.js
@@ -4,7 +4,7 @@
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 
-import {fakeChromeVersion, fakeComponents, fakeDeviceRegions, fakeDeviceSkus, fakeRsuChallengeQrCode, fakeStates} from './fake_data.js';
+import {fakeCalibrationComponents, fakeChromeVersion, fakeComponents, fakeDeviceRegions, fakeDeviceSkus, fakeRsuChallengeQrCode, fakeStates} from './fake_data.js';
 import {FakeShimlessRmaService} from './fake_shimless_rma_service.js'
 import {CalibrationSetupInstruction, NetworkConfigServiceInterface, RmadErrorCode, ShimlessRmaService, ShimlessRmaServiceInterface} from './shimless_rma_types.js';
 
@@ -66,6 +66,7 @@
 
   service.setGetCalibrationSetupInstructionsResult(
       CalibrationSetupInstruction.kCalibrationInstructionPlaceLidOnFlatSurface);
+  service.setGetCalibrationComponentListResult(fakeCalibrationComponents);
 
   // Set the fake service.
   setShimlessRmaServiceForTesting(service);
diff --git a/ash/webui/shimless_rma/resources/onboarding_select_components_page.js b/ash/webui/shimless_rma/resources/onboarding_select_components_page.js
index 2e32c9b..7156fd6 100644
--- a/ash/webui/shimless_rma/resources/onboarding_select_components_page.js
+++ b/ash/webui/shimless_rma/resources/onboarding_select_components_page.js
@@ -9,6 +9,7 @@
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {ComponentTypeToId, ComponentTypeToName} from './data.js';
 import {getShimlessRmaService} from './mojo_interface_provider.js';
 import {Component, ComponentRepairStatus, ComponentType, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
 
@@ -24,58 +25,6 @@
 let ComponentCheckbox;
 
 /**
- * @type {!Object<!ComponentType, string>}
- */
-const ComponentTypeToName = {
-  [ComponentType.kAudioCodec]: 'Audio',
-  [ComponentType.kBattery]: 'Battery',
-  [ComponentType.kStorage]: 'Storage',
-  [ComponentType.kVpdCached]: 'Vpd Cached',
-  [ComponentType.kNetwork]: 'Network',
-  [ComponentType.kCamera]: 'Camera',
-  [ComponentType.kStylus]: 'Stylus',
-  [ComponentType.kTouchpad]: 'Touchpad',
-  [ComponentType.kTouchsreen]: 'Touchscreen',
-  [ComponentType.kDram]: 'Memory',
-  [ComponentType.kDisplayPanel]: 'Display',
-  [ComponentType.kCellular]: 'Cellular',
-  [ComponentType.kEthernet]: 'Ethernet',
-  [ComponentType.kWireless]: 'Wireless',
-  [ComponentType.kGyroscope]: 'Gyroscope',
-  [ComponentType.kBaseAccelerometer]: 'Base Accelerometer',
-  [ComponentType.kLidAccelerometer]: 'Lid Accelerometer',
-  [ComponentType.kScreen]: 'Screen',
-  [ComponentType.kKeyboard]: 'Keyboard',
-  [ComponentType.kPowerButton]: 'Power Button'
-};
-
-/**
- * @type {!Object<!ComponentType, string>}
- */
-const ComponentTypeToId = {
-  [ComponentType.kAudioCodec]: 'componentAudio',
-  [ComponentType.kBattery]: 'componentBattery',
-  [ComponentType.kStorage]: 'componentStorage',
-  [ComponentType.kVpdCached]: 'componentVpd Cached',
-  [ComponentType.kNetwork]: 'componentNetwork',
-  [ComponentType.kCamera]: 'componentCamera',
-  [ComponentType.kStylus]: 'componentStylus',
-  [ComponentType.kTouchpad]: 'componentTouchpad',
-  [ComponentType.kTouchsreen]: 'componentTouchscreen',
-  [ComponentType.kDram]: 'componentDram',
-  [ComponentType.kDisplayPanel]: 'componentDisplayPanel',
-  [ComponentType.kCellular]: 'componentCellular',
-  [ComponentType.kEthernet]: 'componentEthernet',
-  [ComponentType.kWireless]: 'componentWireless',
-  [ComponentType.kGyroscope]: 'componentGyroscope',
-  [ComponentType.kBaseAccelerometer]: 'componentBaseAccelerometer',
-  [ComponentType.kLidAccelerometer]: 'componentLidAccelerometer',
-  [ComponentType.kScreen]: 'componentScreen',
-  [ComponentType.kKeyboard]: 'componentKeyboard',
-  [ComponentType.kPowerButton]: 'componentPowerButton'
-};
-
-/**
  * @fileoverview
  * 'onboarding-select-components-page' is the page for selecting the components
  * that were replaced during repair.
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_page.html b/ash/webui/shimless_rma/resources/reimaging_calibration_page.html
index f233025..04357e2 100644
--- a/ash/webui/shimless_rma/resources/reimaging_calibration_page.html
+++ b/ash/webui/shimless_rma/resources/reimaging_calibration_page.html
@@ -1,24 +1,26 @@
 <style include="cr-shared-style shimless-rma-shared">
   iron-icon {
-    width: 300px;
     height: 200px;
+    width: 300px;
   }
 </style>
 
 <base-page orientation="column">
   <div slot="header">
-    <!-- TODO(joonbug): update for i18n -->
-    <h1>Calibrate the device's accelerometer</h1>
-    <div id="preCalibration" hidden$="[[calibrationObserverReceiver_]]">
-      <span>Please place the device on a flat surface before proceeding</span>
-    </div>
-    <div id="calibration" hidden$="[[!calibrationObserverReceiver_]]">
-      <span>Please wait while accelerometer is calibrated</span>
-    </div>
-    <span hidden$="[[!calibrationComplete_]]">Completed</span>
+    <!-- TODO(gavindodd): update for i18n -->
+    <h1>Calibrate device components</h1>
   </div>
   <div slot="body">
-    <!-- TODO(joonbug): Replace with accelerometer calibration image -->
-    <iron-icon icon="shimless:shimless-placeholder"></iron-icon>
+    <div>
+      <template is="dom-repeat" items="{{componentCheckboxes_}}" as="component">
+        <calibration-component-chip id="[[component.id]]"
+          skip="{{component.skip}}"
+          completed="{{component.completed}}"
+          failed$="[[component.failed]]"
+          disabled$="[[component.disabled]]"
+          component-name="[[component.name]]">
+        </calibration-component-chip>
+      </template>
+    </div>
   </div>
 </base-page>
diff --git a/ash/webui/shimless_rma/resources/reimaging_calibration_page.js b/ash/webui/shimless_rma/resources/reimaging_calibration_page.js
index d2400e9..a2deb4f 100644
--- a/ash/webui/shimless_rma/resources/reimaging_calibration_page.js
+++ b/ash/webui/shimless_rma/resources/reimaging_calibration_page.js
@@ -4,21 +4,39 @@
 
 import 'chrome://resources/cr_elements/icons.m.js';
 import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js';
-import './shimless_rma_shared_css.js';
 import './base_page.js';
+import './calibration_component_chip.js';
 import './icons.js';
+import './shimless_rma_shared_css.js';
 
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
+import {ComponentTypeToId, ComponentTypeToName} from './data.js';
 import {getShimlessRmaService} from './mojo_interface_provider.js';
-import {CalibrationComponentStatus, CalibrationObserverInterface, CalibrationObserverReceiver, CalibrationOverallStatus, CalibrationStatus, ComponentType, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
+import {CalibrationComponentStatus, CalibrationStatus, ComponentType, ShimlessRmaServiceInterface, StateResult} from './shimless_rma_types.js';
 
 /**
  * @fileoverview
- * 'reimaging-calibration-page' is for recalibration of the
- * various components during the reimaging process.
+ * 'reimaging-calibration-page' is to inform the user which components will be
+ * calibrated and allow them to skip components if necessary.
+ * (Skipping components could allow the device to be in a usable, but not fully
+ * functioning state.)
  */
+
+/**
+ * @typedef {{
+ *   component: !ComponentType,
+ *   id: string,
+ *   name: string,
+ *   skip: boolean,
+ *   completed: boolean,
+ *   failed: boolean,
+ *   disabled: boolean
+ * }}
+ */
+let ComponentCheckbox;
+
 export class ReimagingCalibrationPageElement extends PolymerElement {
   static get is() {
     return 'reimaging-calibration-page';
@@ -30,83 +48,77 @@
 
   static get properties() {
     return {
-      /** @type {ComponentType} */
-      repairedComponent: {
-        type: Object,
-        value: null,
+      /** @private {!Array<!ComponentCheckbox>} */
+      componentCheckboxes_: {
+        type: Array,
+        value: () => [],
       },
-
-      /** @private {ShimlessRmaServiceInterface} */
-      shimlessRmaService_: {
-        type: Object,
-        value: null,
-      },
-
-      /**
-       * Receiver responsible for observing battery health.
-       * @protected {CalibrationObserverReceiver}
-       */
-      calibrationObserverReceiver_: {
-        type: Object,
-        value: null,
-      },
-
-      /** @protected */
-      calibrationComplete_: {
-        type: Boolean,
-        value: false,
-      }
     };
   }
 
+  constructor() {
+    super();
+    /** @private {ShimlessRmaServiceInterface} */
+    this.shimlessRmaService_ = getShimlessRmaService();
+  }
+
   /** @override */
   ready() {
     super.ready();
-    this.shimlessRmaService_ = getShimlessRmaService();
-  }
-
-
-  /** @return {!Promise<!StateResult>} */
-  onNextButtonClick() {
-    assert(this.repairedComponent);
-
-    if (!this.calibrationObserverReceiver_) {
-      this.observeCalibrationProgress_();
-      return Promise.reject();
-    }
-
-    if (this.calibrationComplete_) {
-      return this.shimlessRmaService_.transitionNextState();
-    }
-    return Promise.reject(new Error('Calibration is not complete.'));
-  }
-
-  /**
-   * Implements CalibrationObserver.onCalibrationUpdated()
-   * @param {!CalibrationComponentStatus} componentStatus
-   */
-  onCalibrationUpdated(componentStatus) {
-    if (this.repairedComponent === componentStatus.component &&
-        componentStatus.status === CalibrationStatus.kCalibrationComplete) {
-      this.calibrationComplete_ = true;
-    }
-  }
-
-  /**
-   * Implements CalibrationObserver.onCalibrationUpdated()
-   * @param {!CalibrationOverallStatus} status
-   */
-  onCalibrationStepComplete(status) {
-    // TODO(gavindodd): Handle calibration step complete observation.
+    this.getInitialComponentsList_();
   }
 
   /** @private */
-  observeCalibrationProgress_() {
-    this.calibrationObserverReceiver_ = new CalibrationObserverReceiver(
-        /** @type {!CalibrationObserverInterface} */ (this));
+  getInitialComponentsList_() {
+    this.shimlessRmaService_.getCalibrationComponentList().then((result) => {
+      if (!result || !result.hasOwnProperty('components')) {
+        // TODO(gavindodd): Set an error state?
+        console.error('Could not get components!');
+        return;
+      }
 
-    this.shimlessRmaService_.observeCalibrationProgress(
-        this.calibrationObserverReceiver_.$.bindNewPipeAndPassRemote());
+      /** @type {!Array<!ComponentCheckbox>} */
+      let componentList = [];
+      result.components.forEach(item => {
+        const component = assert(item.component);
+
+        componentList.push({
+          component: item.component,
+          id: ComponentTypeToId[item.component],
+          name: ComponentTypeToName[item.component],
+          skip: item.status === CalibrationStatus.kCalibrationSkip,
+          completed: item.status === CalibrationStatus.kCalibrationComplete,
+          failed: item.status === CalibrationStatus.kCalibrationFailed,
+          disabled: item.status === CalibrationStatus.kCalibrationComplete ||
+              item.status === CalibrationStatus.kCalibrationInProgress
+        });
+      });
+      this.componentCheckboxes_ = componentList;
+    });
+  }
+
+  /**
+   * @private
+   * @return {!Array<!CalibrationComponentStatus>}
+   */
+  getComponentsList_() {
+    return this.componentCheckboxes_.map(item => {
+      /** @type {!CalibrationStatus} */
+      let status = CalibrationStatus.kCalibrationWaiting;
+      if (item.skip) {
+        status = CalibrationStatus.kCalibrationSkip;
+      } else if (item.completed) {
+        status = CalibrationStatus.kCalibrationComplete;
+      } else if (item.disabled) {
+        status = CalibrationStatus.kCalibrationInProgress;
+      }
+      return {component: item.component, status: status, progress: 0.0};
+    });
+  }
+
+  /** @return {!Promise<!StateResult>} */
+  onNextButtonClick() {
+    return this.shimlessRmaService_.startCalibration(this.getComponentsList_());
   }
 };
 
diff --git a/ash/webui/shimless_rma/resources/wrapup_restock_page.html b/ash/webui/shimless_rma/resources/wrapup_restock_page.html
index f9e56ea..b0335fd 100644
--- a/ash/webui/shimless_rma/resources/wrapup_restock_page.html
+++ b/ash/webui/shimless_rma/resources/wrapup_restock_page.html
@@ -12,7 +12,7 @@
     <p>Choose to shutdown and restock mainboard or continue to finalize this
       device.
     </p>
-    <cr-button id="checkUpdate" on-click="onShutdownButtonClicked_">
+    <cr-button id="shutdown" on-click="onShutdownButtonClicked_">
       Shutdown
     </cr-button>
   </div>
diff --git a/ash/wm/desks/DEPS b/ash/wm/desks/DEPS
new file mode 100644
index 0000000..f885889
--- /dev/null
+++ b/ash/wm/desks/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+  # TODO(crbug/1251346): Remove.
+  "desks_controller.cc": [
+    "+components/user_manager/user_manager.h",
+  ],
+}
diff --git a/base/allocator/allocator.gni b/base/allocator/allocator.gni
index 596ea6d..5ea237a2 100644
--- a/base/allocator/allocator.gni
+++ b/base/allocator/allocator.gni
@@ -5,6 +5,10 @@
 import("//build/config/chromecast_build.gni")
 import("//build/config/sanitizers/sanitizers.gni")
 
+if (is_ios) {
+  import("//build/config/ios/ios_sdk.gni")
+}
+
 # Sanitizers replace the allocator, don't use our own.
 _is_using_sanitizers = is_asan || is_hwasan || is_lsan || is_tsan || is_msan
 
@@ -53,7 +57,8 @@
   # not, and redesign or remove the flag accordingly.  We may want to assert a
   # possible conflict between |use_allocator = "partition"| and
   # |use_partition_alloc = true| rather than prioritizing use_partition_alloc.
-  use_partition_alloc = !is_ios  # Never use PartitionAlloc on iOS.
+  # TODO(crbug.com/1250788): Enable use_partition_alloc on iOS device builds.
+  use_partition_alloc = !is_ios || target_environment == "simulator"
 
   # Set use_backup_ref_ptr true to use BackupRefPtr (BRP) as the implementation
   # of raw_ptr<T>, and enable PartitionAlloc support for it. The _fake option
diff --git a/base/allocator/partition_allocator/page_allocator_internals_posix.h b/base/allocator/partition_allocator/page_allocator_internals_posix.h
index 467de1a..bdf3c1b8 100644
--- a/base/allocator/partition_allocator/page_allocator_internals_posix.h
+++ b/base/allocator/partition_allocator/page_allocator_internals_posix.h
@@ -38,7 +38,7 @@
 #define MAP_ANONYMOUS MAP_ANON
 #endif
 
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
 
 // SecTaskGetCodeSignStatus is marked as unavailable on macOS, although it’s
 // available on iOS and other Apple operating systems. It is, in fact, present
@@ -54,7 +54,7 @@
     API_AVAILABLE(macos(10.12));
 #pragma clang diagnostic pop
 
-#endif  // OS_APPLE
+#endif  // OS_MAC
 
 namespace base {
 
@@ -84,7 +84,7 @@
 }
 #endif  // defined(OS_ANDROID)
 
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
 // Tests whether the version of macOS supports the MAP_JIT flag and if the
 // current process is signed with the hardened runtime and the allow-jit
 // entitlement, returning whether MAP_JIT should be used to allocate regions
@@ -131,7 +131,7 @@
 
   return mac::CFCast<CFBooleanRef>(jit_entitlement.get()) == kCFBooleanTrue;
 }
-#endif  // defined(OS_APPLE)
+#endif  // defined(OS_MAC)
 
 }  // namespace
 
@@ -158,7 +158,7 @@
   int access_flag = GetAccessFlags(accessibility);
   int map_flags = MAP_ANONYMOUS | MAP_PRIVATE;
 
-#if defined(OS_APPLE)
+#if defined(OS_MAC)
   // On macOS 10.14 and higher, executables that are code signed with the
   // "runtime" option cannot execute writable memory by default. They can opt
   // into this capability by specifying the "com.apple.security.cs.allow-jit"
diff --git a/base/allocator/partition_allocator/starscan/stack/stack.cc b/base/allocator/partition_allocator/starscan/stack/stack.cc
index e15e431..23b9c2fe 100644
--- a/base/allocator/partition_allocator/starscan/stack/stack.cc
+++ b/base/allocator/partition_allocator/starscan/stack/stack.cc
@@ -44,7 +44,7 @@
 #endif
 }
 
-#elif defined(OS_MAC)
+#elif defined(OS_APPLE)
 
 void* GetStackTop() {
   return pthread_get_stackaddr_np(pthread_self());
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java b/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java
index 605fe23..f6cc573 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/Batch.java
@@ -29,16 +29,6 @@
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
 public @interface Batch {
-    /**
-     * This annotation can be added in addition to @Batch to split batches based on @Features
-     * annotation. This will ensure that native features are configured correctly.
-     *
-     * @deprecated crbug.com/1187705: SplitByFeature is always assumed to be added now.
-     */
-    @Target(ElementType.TYPE)
-    @Retention(RetentionPolicy.RUNTIME)
-    @Deprecated
-    public @interface SplitByFeature {}
 
     public String value();
 
diff --git a/build/android/gyp/lint.py b/build/android/gyp/lint.py
index 61763c1..09f98f9 100755
--- a/build/android/gyp/lint.py
+++ b/build/android/gyp/lint.py
@@ -80,7 +80,8 @@
                          resource_sources=None,
                          custom_lint_jars=None,
                          custom_annotation_zips=None,
-                         android_sdk_version=None):
+                         android_sdk_version=None,
+                         baseline_path=None):
   project = ElementTree.Element('project')
   root = ElementTree.SubElement(project, 'root')
   # Run lint from output directory: crbug.com/1115594
@@ -88,6 +89,9 @@
   sdk = ElementTree.SubElement(project, 'sdk')
   # Lint requires that the sdk path be an absolute path.
   sdk.set('dir', os.path.abspath(android_sdk_root))
+  if baseline_path is not None:
+    baseline = ElementTree.SubElement(project, 'baseline')
+    baseline.set('file', baseline_path)
   cache = ElementTree.SubElement(project, 'cache')
   cache.set('dir', cache_dir)
   main_module = ElementTree.SubElement(project, 'module')
@@ -219,8 +223,6 @@
       ','.join(_DISABLED_ALWAYS),
   ]
 
-  if baseline:
-    cmd.extend(['--baseline', baseline])
   if testonly_target:
     cmd.extend(['--disable', ','.join(_DISABLED_FOR_TESTS)])
 
@@ -300,7 +302,7 @@
                                            classpath, srcjar_sources,
                                            resource_sources, custom_lint_jars,
                                            custom_annotation_zips,
-                                           android_sdk_version)
+                                           android_sdk_version, baseline)
 
   project_xml_path = os.path.join(lint_gen_dir, 'project.xml')
   _WriteXmlFile(project_file_root, project_xml_path)
diff --git a/build/android/gyp/merge_manifest.py b/build/android/gyp/merge_manifest.py
index d0a93a8..d4ea203e 100755
--- a/build/android/gyp/merge_manifest.py
+++ b/build/android/gyp/merge_manifest.py
@@ -22,8 +22,8 @@
     os.path.join('common', 'common.jar'),
     os.path.join('sdk-common', 'sdk-common.jar'),
     os.path.join('sdklib', 'sdklib.jar'),
-    os.path.join('external', 'com', 'google', 'guava', 'guava', '28.1-jre',
-                 'guava-28.1-jre.jar'),
+    os.path.join('external', 'com', 'google', 'guava', 'guava', '30.1-jre',
+                 'guava-30.1-jre.jar'),
     os.path.join('external', 'kotlin-plugin-ij', 'Kotlin', 'kotlinc', 'lib',
                  'kotlin-stdlib.jar'),
     os.path.join('external', 'com', 'google', 'code', 'gson', 'gson', '2.8.6',
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
index 54cb92a..717971e 100644
--- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py
+++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -513,12 +513,15 @@
         # Feature flags won't work in instrumentation tests unless the activity
         # is restarted.
         # Tests with identical features are grouped to minimize restarts.
-        if 'Features$EnableFeatures' in annotations:
-          batch_name += '|enabled:' + ','.join(
-              sorted(annotations['Features$EnableFeatures']['value']))
-        if 'Features$DisableFeatures' in annotations:
-          batch_name += '|disabled:' + ','.join(
-              sorted(annotations['Features$DisableFeatures']['value']))
+        # UnitTests that specify flags always use Features.JUnitProcessor, so
+        # they don't need to be split.
+        if batch_name != 'UnitTests':
+          if 'Features$EnableFeatures' in annotations:
+            batch_name += '|enabled:' + ','.join(
+                sorted(annotations['Features$EnableFeatures']['value']))
+          if 'Features$DisableFeatures' in annotations:
+            batch_name += '|disabled:' + ','.join(
+                sorted(annotations['Features$DisableFeatures']['value']))
 
         if not batch_name in batched_tests:
           batched_tests[batch_name] = []
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 897b401..f52a51f 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-6.20210920.0.1
+6.20210920.2.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index e1d55ab..f52a51f 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-6.20210920.1.1
+6.20210920.2.1
diff --git a/build/util/lib/common/chrome_test_server_spawner.py b/build/util/lib/common/chrome_test_server_spawner.py
index 887a901..aab0d079 100644
--- a/build/util/lib/common/chrome_test_server_spawner.py
+++ b/build/util/lib/common/chrome_test_server_spawner.py
@@ -44,10 +44,6 @@
        os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver')))
 
 
-# The timeout (in seconds) of starting up the Python test server.
-_TEST_SERVER_STARTUP_TIMEOUT = 10
-
-
 def _GetServerTypeCommandLine(server_type):
   """Returns the command-line by the given server type.
 
@@ -108,30 +104,25 @@
     self.port_forwarder = port_forwarder
     self.test_server_process = None
     self.is_ready = False
-    self.host_port = self.arguments['port']
+    self.host_port = 0
     self.host_ocsp_port = 0
     assert isinstance(self.host_port, int)
     # The forwarder device port now is dynamically allocated.
     self.forwarder_device_port = 0
     self.forwarder_ocsp_device_port = 0
-    # Anonymous pipe in order to get port info from test server.
-    self.pipe_in = None
-    self.pipe_out = None
     self.process = None
     self.command_line = []
 
-  def _WaitToStartAndGetPortFromTestServer(self):
+  def _WaitToStartAndGetPortFromTestServer(self, pipe_in):
     """Waits for the Python test server to start and gets the port it is using.
 
     The port information is passed by the Python test server with a pipe given
-    by self.pipe_in. It is written as a result to |self.host_port|.
+    by |pipe_in|. It is written as a result to |self.host_port|.
 
     Returns:
       Whether the port used by the test server was successfully fetched.
     """
-    assert self.host_port == 0 and self.pipe_in
-    (in_fds, _, _) = select.select([self.pipe_in, ], [], [],
-                                   _TEST_SERVER_STARTUP_TIMEOUT)
+    (in_fds, _, _) = select.select([pipe_in], [], [])
     if len(in_fds) == 0:
       _logger.error('Failed to wait to the Python test server to be started.')
       return False
@@ -141,14 +132,14 @@
     # configured to use little-endian.
     # TODO(jnd): Change the Python test server and local_test_server_*.cc to
     # use a unified byte order (either big-endian or little-endian).
-    data_length = os.read(self.pipe_in, struct.calcsize('=L'))
+    data_length = os.read(pipe_in, struct.calcsize('=L'))
     if data_length:
       (data_length,) = struct.unpack('=L', data_length)
       assert data_length
     if not data_length:
       _logger.error('Failed to get length of server data.')
       return False
-    server_data_json = os.read(self.pipe_in, data_length)
+    server_data_json = os.read(pipe_in, data_length)
     if not server_data_json:
       _logger.error('Failed to get server data.')
       return False
@@ -173,7 +164,7 @@
 
     return self.port_forwarder.WaitPortNotAvailable(self.host_port)
 
-  def _GenerateCommandLineArguments(self):
+  def _GenerateCommandLineArguments(self, pipe_out):
     """Generates the command line to run the test server.
 
     Note that all options are processed by following the definitions in
@@ -189,12 +180,8 @@
     if type_cmd:
       self.command_line.append(type_cmd)
 
-    # Use a pipe to get the port given by the instance of Python test server
-    # if the test does not specify the port.
-    assert self.host_port == args_copy['port']
-    if self.host_port == 0:
-      (self.pipe_in, self.pipe_out) = os.pipe()
-      self.command_line.append('--startup-pipe=%d' % self.pipe_out)
+    # Use a pipe to get the port given by the Python test server.
+    self.command_line.append('--startup-pipe=%d' % pipe_out)
 
     # Pass the remaining arguments as-is.
     for key, values in args_copy.iteritems():
@@ -206,7 +193,7 @@
         else:
           self.command_line.append('--%s=%s' % (key, value))
 
-  def _CloseUnnecessaryFDsForTestServerProcess(self):
+  def _CloseUnnecessaryFDsForTestServerProcess(self, pipe_out):
     # This is required to avoid subtle deadlocks that could be caused by the
     # test server child process inheriting undesirable file descriptors such as
     # file lock file descriptors. Note stdin, stdout, and stderr (0-2) are left
@@ -214,7 +201,7 @@
     # fds filled, or the test server will accidentally open other fds at those
     # numbers.
     for fd in xrange(3, 1024):
-      if fd != self.pipe_out:
+      if fd != pipe_out:
         try:
           os.close(fd)
         except:
@@ -223,93 +210,79 @@
   def run(self):
     _logger.info('Start running the thread!')
     self.wait_event.clear()
-    self._GenerateCommandLineArguments()
-    # TODO(crbug.com/941669): When this script is ported to Python 3, replace
-    # 'vpython3' below with sys.executable. The call to
-    # vpython3 -vpython-tool install below can also be removed.
-    command = [
-        'vpython3',
-        os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver',
-                     'testserver.py')
-    ] + self.command_line
-    _logger.info('Running: %s', command)
 
-    # Disable PYTHONUNBUFFERED because it has a bad interaction with the
-    # testserver. Remove once this interaction is fixed.
-    unbuf = os.environ.pop('PYTHONUNBUFFERED', None)
+    # Set up a pipe for the server to report when it has started.
+    pipe_in, pipe_out = os.pipe()
+    try:
+      self._GenerateCommandLineArguments(pipe_out)
+      # TODO(crbug.com/941669): When this script is ported to Python 3, replace
+      # 'vpython3' below with sys.executable.
+      command = [
+          'vpython3',
+          os.path.join(_DIR_SOURCE_ROOT, 'net', 'tools', 'testserver',
+                       'testserver.py')
+      ] + self.command_line
+      _logger.info('Running: %s', command)
 
-    # Pass _DIR_SOURCE_ROOT as the child's working directory so that relative
-    # paths in the arguments are resolved correctly. devnull can be replaced
-    # with subprocess.DEVNULL in Python 3.
-    with open(os.devnull, 'r+b') as devnull:
-      # _WaitToStartAndGetPortFromTestServer has a short timeout. If the
-      # vpython3 cache is not initialized, launching the test server can take
-      # some time. Prewarm the cache before running the server.
-      subprocess.check_call(
-          [
-              'vpython3', '-vpython-spec',
-              os.path.join(_DIR_SOURCE_ROOT, '.vpython3'), '-vpython-tool',
-              'install'
-          ],
-          preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess,
-          stdin=devnull,
-          stdout=None,
-          stderr=None,
-          cwd=_DIR_SOURCE_ROOT)
+      # Disable PYTHONUNBUFFERED because it has a bad interaction with the
+      # testserver. Remove once this interaction is fixed.
+      unbuf = os.environ.pop('PYTHONUNBUFFERED', None)
 
-      self.process = subprocess.Popen(
-          command,
-          preexec_fn=self._CloseUnnecessaryFDsForTestServerProcess,
-          stdin=devnull,
-          # Preserve stdout and stderr from the test server.
-          stdout=None,
-          stderr=None,
-          cwd=_DIR_SOURCE_ROOT)
-    # Close self.pipe_out early. If self.process crashes, this will be visible
-    # in _WaitToStartAndGetPortFromTestServer's select loop.
-    if self.pipe_out:
-      os.close(self.pipe_out)
-      self.pipe_out = None
-    if unbuf:
-      os.environ['PYTHONUNBUFFERED'] = unbuf
-    if self.process:
-      if self.pipe_in:
-        self.is_ready = self._WaitToStartAndGetPortFromTestServer()
-      else:
-        self.is_ready = self.port_forwarder.WaitPortNotAvailable(self.host_port)
+      # Pass _DIR_SOURCE_ROOT as the child's working directory so that relative
+      # paths in the arguments are resolved correctly. devnull can be replaced
+      # with subprocess.DEVNULL in Python 3.
+      with open(os.devnull, 'r+b') as devnull:
+        self.process = subprocess.Popen(
+            command,
+            preexec_fn=lambda: self._CloseUnnecessaryFDsForTestServerProcess(
+                pipe_out),
+            stdin=devnull,
+            # Preserve stdout and stderr from the test server.
+            stdout=None,
+            stderr=None,
+            cwd=_DIR_SOURCE_ROOT)
+      # Close pipe_out early. If self.process crashes, this will be visible
+      # in _WaitToStartAndGetPortFromTestServer's select loop.
+      os.close(pipe_out)
+      pipe_out = -1
+      if unbuf:
+        os.environ['PYTHONUNBUFFERED'] = unbuf
+      self.is_ready = self._WaitToStartAndGetPortFromTestServer(pipe_in)
 
-    if self.is_ready:
-      port_map = [(0, self.host_port)]
-      if self.host_ocsp_port:
-        port_map.extend([(0, self.host_ocsp_port)])
-      self.port_forwarder.Map(port_map)
+      if self.is_ready:
+        port_map = [(0, self.host_port)]
+        if self.host_ocsp_port:
+          port_map.extend([(0, self.host_ocsp_port)])
+        self.port_forwarder.Map(port_map)
 
-      self.forwarder_device_port = \
-          self.port_forwarder.GetDevicePortForHostPort(self.host_port)
-      if self.host_ocsp_port:
-        self.forwarder_ocsp_device_port = \
-            self.port_forwarder.GetDevicePortForHostPort(self.host_ocsp_port)
+        self.forwarder_device_port = \
+            self.port_forwarder.GetDevicePortForHostPort(self.host_port)
+        if self.host_ocsp_port:
+          self.forwarder_ocsp_device_port = \
+              self.port_forwarder.GetDevicePortForHostPort(self.host_ocsp_port)
 
-      # Check whether the forwarder is ready on the device.
-      self.is_ready = self.forwarder_device_port and \
-          self.port_forwarder.WaitDevicePortReady(self.forwarder_device_port)
+        # Check whether the forwarder is ready on the device.
+        self.is_ready = self.forwarder_device_port and \
+            self.port_forwarder.WaitDevicePortReady(self.forwarder_device_port)
 
-    # Wake up the request handler thread.
-    self.ready_event.set()
-    # Keep thread running until Stop() gets called.
-    self.stop_event.wait()
-    if self.process.poll() is None:
-      self.process.kill()
-      # Wait for process to actually terminate.
-      # (crbug.com/946475)
-      self.process.wait()
+      # Wake up the request handler thread.
+      self.ready_event.set()
+      # Keep thread running until Stop() gets called.
+      self.stop_event.wait()
+      if self.process.poll() is None:
+        self.process.kill()
+        # Wait for process to actually terminate.
+        # (crbug.com/946475)
+        self.process.wait()
 
-    self.port_forwarder.Unmap(self.forwarder_device_port)
-    self.process = None
-    self.is_ready = False
-    if self.pipe_in:
-      os.close(self.pipe_in)
-      self.pipe_in = None
+      self.port_forwarder.Unmap(self.forwarder_device_port)
+      self.process = None
+      self.is_ready = False
+    finally:
+      if pipe_in >= 0:
+        os.close(pipe_in)
+      if pipe_out >= 0:
+        os.close(pipe_out)
     _logger.info('Test-server has died.')
     self.wait_event.set()
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index e82c43c..67624de8 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1340,6 +1340,7 @@
     "//chrome/browser/password_manager/android_test_helpers:test_support_java",
     "//chrome/browser/performance_hints/android:java",
     "//chrome/browser/policy/android:java",
+    "//chrome/browser/power_bookmarks:proto_java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/privacy_sandbox/android:java",
     "//chrome/browser/privacy_sandbox/android:javatests",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index fc70f891..5407a0c 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -690,6 +690,7 @@
   "java/res/layout/passwords_error_dialog.xml",
   "java/res/layout/passwords_progress_dialog.xml",
   "java/res/layout/power_bookmark_shopping_item_row.xml",
+  "java/res/layout/power_bookmark_tag_chip_list.xml",
   "java/res/layout/powered_by_chrome_footer.xml",
   "java/res/layout/preference_text_scale.xml",
   "java/res/layout/radio_button_group_homepage_preference.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 46273c6..b3180d0 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -176,6 +176,7 @@
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkUndoController.java",
   "java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java",
   "java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkShoppingItemRow.java",
+  "java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java",
   "java/src/org/chromium/chrome/browser/bookmarks/ReadingListSectionHeader.java",
   "java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetContent.java",
   "java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 1be1a84..a9bb143 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -80,6 +80,7 @@
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoDismissTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkPersonalizedSigninPromoTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java",
+  "javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTest.java",
   "javatests/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetTest.java",
   "javatests/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivityTest.java",
diff --git a/chrome/android/expectations/lint-baseline.xml b/chrome/android/expectations/lint-baseline.xml
index 7d4268d..072cffc5 100644
--- a/chrome/android/expectations/lint-baseline.xml
+++ b/chrome/android/expectations/lint-baseline.xml
@@ -1,1940 +1,5036 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+<issues format="5" by="lint 7.0.0" client="cli" variant="all" version="4.1.0">
 
     <issue
-        id="WrongConstant"
-        message="Must be one of: ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS"
-        errorLine1="                contentsShowing ? View.IMPORTANT_FOR_ACCESSIBILITY_AUTO"
-        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="ResourceType"
+        message="Expected a color resource id (`R.color.`) but received an RGB integer">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java"
-            line="568"
-            column="35"/>
+            file="../../components/page_info/android/java/src/org/chromium/components/page_info/PageInfoPermissionsController.java"
+            line="66"/>
+    </issue>
+
+    <issue
+        id="DiscouragedPrivateApi"
+        message="Reflective access to sPackageManager, which is not part of the public SDK and therefore likely to change in future Android releases">
+        <location
+            file="../../components/embedder_support/android/java/src/org/chromium/components/embedder_support/application/FontPreloadingWorkaround.java"
+            line="68"/>
+    </issue>
+
+    <issue
+        id="DiscouragedPrivateApi"
+        message="Reflective access to PRIMARY_DIRECTORY, which is not part of the public SDK and therefore likely to change in future Android releases">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageArchivePublisherBridge.java"
+            line="164"/>
+    </issue>
+
+    <issue
+        id="DiscouragedPrivateApi"
+        message="Reflective access to violationsBeingTimed, which is not part of the public SDK and therefore likely to change in future Android releases">
+        <location
+            file="../../components/strictmode/android/java/src/org/chromium/components/strictmode/ReflectiveThreadStrictModeInterceptor.java"
+            line="104"/>
+    </issue>
+
+    <issue
+        id="DiscouragedPrivateApi"
+        message="Reflective access to mask, which is not part of the public SDK and therefore likely to change in future Android releases">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/interfaces/StrictModeWorkaround.java"
+            line="32"/>
+    </issue>
+
+    <issue
+        id="DiscouragedPrivateApi"
+        message="Reflective access to sEnforceThreadChecking, which is not part of the public SDK and therefore likely to change in future Android releases">
+        <location
+            file="../../android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java"
+            line="398"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java"
+            line="173"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java"
+            line="175"/>
+    </issue>
+
+    <issue
+        id="NewApi"
+        message="">
+        <location
+            file="../../chrome/browser/optimization_guide/android/java/src/org/chromium/chrome/browser/optimization_guide/OptimizationGuidePushNotificationManager.java"
+            line="65"/>
     </issue>
 
     <issue
         id="WrongConstant"
-        message="Must be one of: ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS"
-        errorLine1="                                : View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);"
-        errorLine2="                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Must be one of: OmniboxSuggestionType.URL_WHAT_YOU_TYPED, OmniboxSuggestionType.HISTORY_URL, OmniboxSuggestionType.HISTORY_TITLE, OmniboxSuggestionType.HISTORY_BODY, OmniboxSuggestionType.HISTORY_KEYWORD, OmniboxSuggestionType.NAVSUGGEST, OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, OmniboxSuggestionType.SEARCH_HISTORY, OmniboxSuggestionType.SEARCH_SUGGEST, OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, OmniboxSuggestionType.SEARCH_OTHER_ENGINE, OmniboxSuggestionType.EXTENSION_APP_DEPRECATED, OmniboxSuggestionType.CONTACT_DEPRECATED, OmniboxSuggestionType.BOOKMARK_TITLE, OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, OmniboxSuggestionType.CALCULATOR, OmniboxSuggestionType.CLIPBOARD_URL, OmniboxSuggestionType.VOICE_SUGGEST, OmniboxSuggestionType.PHYSICAL_WEB_DEPRECATED, OmniboxSuggestionType.PHYSICAL_WEB_OVERFLOW_DEPRECATED, OmniboxSuggestionType.TAB_SEARCH_DEPRECATED, OmniboxSuggestionType.DOCUMENT_SUGGESTION, OmniboxSuggestionType.PEDAL_DEPRECATED, OmniboxSuggestionType.CLIPBOARD_TEXT, OmniboxSuggestionType.CLIPBOARD_IMAGE, OmniboxSuggestionType.TILE_SUGGESTION, OmniboxSuggestionType.TILE_NAVSUGGEST, OmniboxSuggestionType.NUM_TYPES">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java"
-            line="569"
-            column="35"/>
+            file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java"
+            line="161"/>
     </issue>
 
     <issue
         id="WrongConstant"
-        message="Must be one of: ViewCompat.LAYOUT_DIRECTION_LTR, ViewCompat.LAYOUT_DIRECTION_RTL"
-        errorLine1="        if (ViewCompat.getLayoutDirection(this) == LAYOUT_DIRECTION_LTR) {"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~">
+        message="Must be one of: OmniboxSuggestionType.URL_WHAT_YOU_TYPED, OmniboxSuggestionType.HISTORY_URL, OmniboxSuggestionType.HISTORY_TITLE, OmniboxSuggestionType.HISTORY_BODY, OmniboxSuggestionType.HISTORY_KEYWORD, OmniboxSuggestionType.NAVSUGGEST, OmniboxSuggestionType.SEARCH_WHAT_YOU_TYPED, OmniboxSuggestionType.SEARCH_HISTORY, OmniboxSuggestionType.SEARCH_SUGGEST, OmniboxSuggestionType.SEARCH_SUGGEST_ENTITY, OmniboxSuggestionType.SEARCH_SUGGEST_TAIL, OmniboxSuggestionType.SEARCH_SUGGEST_PERSONALIZED, OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, OmniboxSuggestionType.SEARCH_OTHER_ENGINE, OmniboxSuggestionType.EXTENSION_APP_DEPRECATED, OmniboxSuggestionType.CONTACT_DEPRECATED, OmniboxSuggestionType.BOOKMARK_TITLE, OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, OmniboxSuggestionType.CALCULATOR, OmniboxSuggestionType.CLIPBOARD_URL, OmniboxSuggestionType.VOICE_SUGGEST, OmniboxSuggestionType.PHYSICAL_WEB_DEPRECATED, OmniboxSuggestionType.PHYSICAL_WEB_OVERFLOW_DEPRECATED, OmniboxSuggestionType.TAB_SEARCH_DEPRECATED, OmniboxSuggestionType.DOCUMENT_SUGGESTION, OmniboxSuggestionType.PEDAL_DEPRECATED, OmniboxSuggestionType.CLIPBOARD_TEXT, OmniboxSuggestionType.CLIPBOARD_IMAGE, OmniboxSuggestionType.TILE_SUGGESTION, OmniboxSuggestionType.TILE_NAVSUGGEST, OmniboxSuggestionType.NUM_TYPES">
         <location
-            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ClipDrawableProgressBar.java"
-            line="137"
-            column="52"/>
+            file="../../chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessor.java"
+            line="173"/>
     </issue>
 
     <issue
         id="WrongConstant"
-        message="Must be one of: ViewCompat.ACCESSIBILITY_LIVE_REGION_NONE, ViewCompat.ACCESSIBILITY_LIVE_REGION_POLITE, ViewCompat.ACCESSIBILITY_LIVE_REGION_ASSERTIVE"
-        errorLine1="        ViewCompat.setAccessibilityLiveRegion(messageView, View.ACCESSIBILITY_LIVE_REGION_POLITE);"
-        errorLine2="                                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java"
-            line="132"
-            column="60"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java"
+            line="121"/>
     </issue>
 
     <issue
         id="WrongConstant"
-        message="Must be one of: ViewCompat.LAYOUT_DIRECTION_LTR, ViewCompat.LAYOUT_DIRECTION_RTL"
-        errorLine1="        if (ViewCompat.getLayoutDirection(this) == View.LAYOUT_DIRECTION_RTL) {"
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/MaterialProgressBar.java"
-            line="235"
-            column="52"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java"
+            line="127"/>
     </issue>
 
     <issue
-        id="UnsupportedChromeOsCameraSystemFeature"
-        message="You should look for any camera available on the device, not just the rear"
-        errorLine1="        boolean hasCamera = pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../base/android/java/src/org/chromium/base/SysUtils.java"
-            line="160"
-            column="29"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java"
+            line="127"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            if (AccountUtils.GOOGLE_ACCOUNT_TYPE.equals(desc.type)) return true;"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../components/signin/public/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java"
-            line="188"
-            column="30"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java"
+            line="128"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                IconProvider.getIcon(context, R.drawable.ic_permission_location_filled),"
-        errorLine2="                             ~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/AddressAccessorySheetCoordinator.java"
-            line="39"
-            column="30"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/bottomsheet/BookmarkBottomSheetCoordinator.java"
+            line="128"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            if (mBypassIsReadyToPayServiceInTest) app.bypassIsReadyToPayServiceInTest();"
-        errorLine2="                                                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentAppFinder.java"
-            line="577"
-            column="55"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java"
+            line="64"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            mHandler.onOptionsItemSelected(menuItem);"
-        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java"
-            line="365"
-            column="22"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java"
+            line="71"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            return new EditorTextField(context,"
-        errorLine2="                   ^">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java"
-            line="83"
-            column="20"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java"
+            line="73"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            inputView.getEditText().setOnFocusChangeListener((unusedView, hasFocus) -> {"
-        errorLine2="                      ~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java"
-            line="145"
-            column="23"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkFolderRow.java"
+            line="73"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        View view = new EditorTextField(context,"
-        errorLine2="                    ^">
+        id="WrongConstant"
+        message="Must be one of: BookmarkType.NORMAL, BookmarkType.PARTNER, BookmarkType.READING_LIST, BookmarkType.LAST">
         <location
-            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantViewFactory.java"
-            line="145"
-            column="21"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java"
+            line="406"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                    ((EditorTextField) view).getEditText(), text, delegate::onTextLinkClicked);"
-        errorLine2="                                             ~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: PageTransition.FIRST, PageTransition.LINK, PageTransition.TYPED, PageTransition.AUTO_BOOKMARK, PageTransition.AUTO_SUBFRAME, PageTransition.MANUAL_SUBFRAME, PageTransition.GENERATED, PageTransition.AUTO_TOPLEVEL, PageTransition.FORM_SUBMIT, PageTransition.RELOAD, PageTransition.KEYWORD, PageTransition.KEYWORD_GENERATED, PageTransition.LAST_CORE, PageTransition.CORE_MASK, PageTransition.BLOCKED, PageTransition.FORWARD_BACK, PageTransition.FROM_ADDRESS_BAR, PageTransition.HOME_PAGE, PageTransition.FROM_API, PageTransition.CHAIN_START, PageTransition.CHAIN_END, PageTransition.CLIENT_REDIRECT, PageTransition.SERVER_REDIRECT, PageTransition.IS_REDIRECT_MASK, PageTransition.QUALIFIER_MASK">
         <location
-            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantViewInteractions.java"
-            line="108"
-            column="46"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java"
+            line="166"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                .getAuthenticatorNavigationInterceptor();"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: DirectActionId.GO_BACK, DirectActionId.RELOAD, DirectActionId.GO_FORWARD, DirectActionId.BOOKMARK_THIS_PAGE, DirectActionId.DOWNLOADS, DirectActionId.PREFERENCES, DirectActionId.OPEN_HISTORY, DirectActionId.HELP, DirectActionId.NEW_TAB, DirectActionId.CLOSE_TAB, DirectActionId.CLOSE_ALL_TABS, DirectActionId.FIND_IN_PAGE, DirectActionId.NUM_ENTRIES">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/tab/AuthenticatorNavigationInterceptorTabHelper.java"
-            line="19"
-            column="18"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/directactions/DirectActionUsageHistogram.java"
+            line="81"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return mAutocomplete.getCurrentNativeAutocompleteResult();"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: DownloadState.IN_PROGRESS, DownloadState.COMPLETE, DownloadState.CANCELLED, DownloadState.INTERRUPTED, DownloadState.MAX_DOWNLOAD_STATE">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java"
-            line="425"
-            column="30"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java"
+            line="1548"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                CombinedPolicyProvider.get().registerProvider(new AwPolicyProvider(appContext));"
-        errorLine2="                                                              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: DownloadState.IN_PROGRESS, DownloadState.COMPLETE, DownloadState.CANCELLED, DownloadState.INTERRUPTED, DownloadState.MAX_DOWNLOAD_STATE">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java"
-            line="145"
-            column="63"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java"
+            line="1549"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mViewAndroidDelegate ="
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: DownloadState.IN_PROGRESS, DownloadState.COMPLETE, DownloadState.CANCELLED, DownloadState.INTERRUPTED, DownloadState.MAX_DOWNLOAD_STATE">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
-            line="1388"
-            column="9"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java"
+            line="1550"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                new AwViewAndroidDelegate(mContainerView, mContentsClient, mScrollOffsetManager);"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: WebView.RENDERER_PRIORITY_WAIVED, WebView.RENDERER_PRIORITY_BOUND, WebView.RENDERER_PRIORITY_IMPORTANT">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
-            line="1389"
-            column="17"/>
+            file="../../android_webview/glue/java/src/com/android/webview/chromium/GlueApiHelperForO.java"
+            line="46"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        LoadUrlParams params = LoadUrlParams.createLoadHttpPostParams(url, postData);"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
-            line="1888"
-            column="46"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java"
+            line="463"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mWebContents.evaluateJavaScriptForTests(script, jsCallback);"
-        errorLine2="                     ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
-            line="2885"
-            column="22"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java"
+            line="525"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return FindAddress.findAddress(addr);"
-        errorLine2="                           ~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java"
-            line="172"
-            column="28"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java"
+            line="531"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return FindAddress.findAddress(addr);"
-        errorLine2="                           ~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: RetrieveMetricsTaskStatus.EXECUTION_EXCEPTION, RetrieveMetricsTaskStatus.INTERRUPTED_EXCEPTION">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java"
-            line="172"
-            column="28"/>
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/services/MetricsBridgeService.java"
+            line="203"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="class AwWebContentsDelegateAdapter extends AwWebContentsDelegate {"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: PageTransition.FIRST, PageTransition.LINK, PageTransition.TYPED, PageTransition.AUTO_BOOKMARK, PageTransition.AUTO_SUBFRAME, PageTransition.MANUAL_SUBFRAME, PageTransition.GENERATED, PageTransition.AUTO_TOPLEVEL, PageTransition.FORM_SUBMIT, PageTransition.RELOAD, PageTransition.KEYWORD, PageTransition.KEYWORD_GENERATED, PageTransition.LAST_CORE, PageTransition.CORE_MASK, PageTransition.BLOCKED, PageTransition.FORWARD_BACK, PageTransition.FROM_ADDRESS_BAR, PageTransition.HOME_PAGE, PageTransition.FROM_API, PageTransition.CHAIN_START, PageTransition.CHAIN_END, PageTransition.CLIENT_REDIRECT, PageTransition.SERVER_REDIRECT, PageTransition.IS_REDIRECT_MASK, PageTransition.QUALIFIER_MASK">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
-            line="34"
-            column="44"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java"
+            line="336"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                if (mAwContents.getNavigationController() == null) return;"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ContentSettingsType.DEFAULT, ContentSettingsType.COOKIES, ContentSettingsType.IMAGES, ContentSettingsType.JAVASCRIPT, ContentSettingsType.POPUPS, ContentSettingsType.GEOLOCATION, ContentSettingsType.NOTIFICATIONS, ContentSettingsType.AUTO_SELECT_CERTIFICATE, ContentSettingsType.MIXEDSCRIPT, ContentSettingsType.MEDIASTREAM_MIC, ContentSettingsType.MEDIASTREAM_CAMERA, ContentSettingsType.PROTOCOL_HANDLERS, ContentSettingsType.PPAPI_BROKER, ContentSettingsType.AUTOMATIC_DOWNLOADS, ContentSettingsType.MIDI_SYSEX, ContentSettingsType.SSL_CERT_DECISIONS, ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER, ContentSettingsType.APP_BANNER, ContentSettingsType.SITE_ENGAGEMENT, ContentSettingsType.DURABLE_STORAGE, ContentSettingsType.USB_CHOOSER_DATA, ContentSettingsType.BLUETOOTH_GUARD, ContentSettingsType.BACKGROUND_SYNC, ContentSettingsType.AUTOPLAY, ContentSettingsType.IMPORTANT_SITE_INFO, ContentSettingsType.PERMISSION_AUTOBLOCKER_DATA, ContentSettingsType.ADS, ContentSettingsType.ADS_DATA, ContentSettingsType.MIDI, ContentSettingsType.PASSWORD_PROTECTION, ContentSettingsType.MEDIA_ENGAGEMENT, ContentSettingsType.SOUND, ContentSettingsType.CLIENT_HINTS, ContentSettingsType.SENSORS, ContentSettingsType.ACCESSIBILITY_EVENTS, ContentSettingsType.PAYMENT_HANDLER, ContentSettingsType.USB_GUARD, ContentSettingsType.BACKGROUND_FETCH, ContentSettingsType.INTENT_PICKER_DISPLAY, ContentSettingsType.IDLE_DETECTION, ContentSettingsType.SERIAL_GUARD, ContentSettingsType.SERIAL_CHOOSER_DATA, ContentSettingsType.PERIODIC_BACKGROUND_SYNC, ContentSettingsType.BLUETOOTH_SCANNING, ContentSettingsType.HID_GUARD, ContentSettingsType.HID_CHOOSER_DATA, ContentSettingsType.WAKE_LOCK_SCREEN, ContentSettingsType.WAKE_LOCK_SYSTEM, ContentSettingsType.LEGACY_COOKIE_ACCESS, ContentSettingsType.FILE_SYSTEM_WRITE_GUARD, ContentSettingsType.INSTALLED_WEB_APP_METADATA, ContentSettingsType.NFC, ContentSettingsType.BLUETOOTH_CHOOSER_DATA, ContentSettingsType.CLIPBOARD_READ_WRITE, ContentSettingsType.CLIPBOARD_SANITIZED_WRITE, ContentSettingsType.SAFE_BROWSING_URL_CHECK_DATA, ContentSettingsType.VR, ContentSettingsType.AR, ContentSettingsType.FILE_SYSTEM_READ_GUARD, ContentSettingsType.STORAGE_ACCESS, ContentSettingsType.CAMERA_PAN_TILT_ZOOM, ContentSettingsType.WINDOW_PLACEMENT, ContentSettingsType.INSECURE_PRIVATE_NETWORK, ContentSettingsType.FONT_ACCESS, ContentSettingsType.PERMISSION_AUTOREVOCATION_DATA, ContentSettingsType.FILE_SYSTEM_LAST_PICKED_DIRECTORY, ContentSettingsType.DISPLAY_CAPTURE, ContentSettingsType.FILE_HANDLING, ContentSettingsType.FILE_SYSTEM_ACCESS_CHOOSER_DATA, ContentSettingsType.FEDERATED_IDENTITY_SHARING, ContentSettingsType.FEDERATED_IDENTITY_REQUEST, ContentSettingsType.JAVASCRIPT_JIT, ContentSettingsType.HTTP_ALLOWED, ContentSettingsType.FORMFILL_METADATA, ContentSettingsType.FEDERATED_IDENTITY_ACTIVE_SESSION, ContentSettingsType.AUTO_DARK_WEB_CONTENT, ContentSettingsType.NUM_TYPES">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
-            line="186"
-            column="33"/>
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java"
+            line="411"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                        mAwContents.getNavigationController().continuePendingReload();"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ContentSettingsType.DEFAULT, ContentSettingsType.COOKIES, ContentSettingsType.IMAGES, ContentSettingsType.JAVASCRIPT, ContentSettingsType.POPUPS, ContentSettingsType.GEOLOCATION, ContentSettingsType.NOTIFICATIONS, ContentSettingsType.AUTO_SELECT_CERTIFICATE, ContentSettingsType.MIXEDSCRIPT, ContentSettingsType.MEDIASTREAM_MIC, ContentSettingsType.MEDIASTREAM_CAMERA, ContentSettingsType.PROTOCOL_HANDLERS, ContentSettingsType.PPAPI_BROKER, ContentSettingsType.AUTOMATIC_DOWNLOADS, ContentSettingsType.MIDI_SYSEX, ContentSettingsType.SSL_CERT_DECISIONS, ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER, ContentSettingsType.APP_BANNER, ContentSettingsType.SITE_ENGAGEMENT, ContentSettingsType.DURABLE_STORAGE, ContentSettingsType.USB_CHOOSER_DATA, ContentSettingsType.BLUETOOTH_GUARD, ContentSettingsType.BACKGROUND_SYNC, ContentSettingsType.AUTOPLAY, ContentSettingsType.IMPORTANT_SITE_INFO, ContentSettingsType.PERMISSION_AUTOBLOCKER_DATA, ContentSettingsType.ADS, ContentSettingsType.ADS_DATA, ContentSettingsType.MIDI, ContentSettingsType.PASSWORD_PROTECTION, ContentSettingsType.MEDIA_ENGAGEMENT, ContentSettingsType.SOUND, ContentSettingsType.CLIENT_HINTS, ContentSettingsType.SENSORS, ContentSettingsType.ACCESSIBILITY_EVENTS, ContentSettingsType.PAYMENT_HANDLER, ContentSettingsType.USB_GUARD, ContentSettingsType.BACKGROUND_FETCH, ContentSettingsType.INTENT_PICKER_DISPLAY, ContentSettingsType.IDLE_DETECTION, ContentSettingsType.SERIAL_GUARD, ContentSettingsType.SERIAL_CHOOSER_DATA, ContentSettingsType.PERIODIC_BACKGROUND_SYNC, ContentSettingsType.BLUETOOTH_SCANNING, ContentSettingsType.HID_GUARD, ContentSettingsType.HID_CHOOSER_DATA, ContentSettingsType.WAKE_LOCK_SCREEN, ContentSettingsType.WAKE_LOCK_SYSTEM, ContentSettingsType.LEGACY_COOKIE_ACCESS, ContentSettingsType.FILE_SYSTEM_WRITE_GUARD, ContentSettingsType.INSTALLED_WEB_APP_METADATA, ContentSettingsType.NFC, ContentSettingsType.BLUETOOTH_CHOOSER_DATA, ContentSettingsType.CLIPBOARD_READ_WRITE, ContentSettingsType.CLIPBOARD_SANITIZED_WRITE, ContentSettingsType.SAFE_BROWSING_URL_CHECK_DATA, ContentSettingsType.VR, ContentSettingsType.AR, ContentSettingsType.FILE_SYSTEM_READ_GUARD, ContentSettingsType.STORAGE_ACCESS, ContentSettingsType.CAMERA_PAN_TILT_ZOOM, ContentSettingsType.WINDOW_PLACEMENT, ContentSettingsType.INSECURE_PRIVATE_NETWORK, ContentSettingsType.FONT_ACCESS, ContentSettingsType.PERMISSION_AUTOREVOCATION_DATA, ContentSettingsType.FILE_SYSTEM_LAST_PICKED_DIRECTORY, ContentSettingsType.DISPLAY_CAPTURE, ContentSettingsType.FILE_HANDLING, ContentSettingsType.FILE_SYSTEM_ACCESS_CHOOSER_DATA, ContentSettingsType.FEDERATED_IDENTITY_SHARING, ContentSettingsType.FEDERATED_IDENTITY_REQUEST, ContentSettingsType.JAVASCRIPT_JIT, ContentSettingsType.HTTP_ALLOWED, ContentSettingsType.FORMFILL_METADATA, ContentSettingsType.FEDERATED_IDENTITY_ACTIVE_SESSION, ContentSettingsType.AUTO_DARK_WEB_CONTENT, ContentSettingsType.NUM_TYPES">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
-            line="190"
-            column="37"/>
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java"
+            line="412"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                        mAwContents.getNavigationController().cancelPendingReload();"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ContentSettingsType.DEFAULT, ContentSettingsType.COOKIES, ContentSettingsType.IMAGES, ContentSettingsType.JAVASCRIPT, ContentSettingsType.POPUPS, ContentSettingsType.GEOLOCATION, ContentSettingsType.NOTIFICATIONS, ContentSettingsType.AUTO_SELECT_CERTIFICATE, ContentSettingsType.MIXEDSCRIPT, ContentSettingsType.MEDIASTREAM_MIC, ContentSettingsType.MEDIASTREAM_CAMERA, ContentSettingsType.PROTOCOL_HANDLERS, ContentSettingsType.PPAPI_BROKER, ContentSettingsType.AUTOMATIC_DOWNLOADS, ContentSettingsType.MIDI_SYSEX, ContentSettingsType.SSL_CERT_DECISIONS, ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER, ContentSettingsType.APP_BANNER, ContentSettingsType.SITE_ENGAGEMENT, ContentSettingsType.DURABLE_STORAGE, ContentSettingsType.USB_CHOOSER_DATA, ContentSettingsType.BLUETOOTH_GUARD, ContentSettingsType.BACKGROUND_SYNC, ContentSettingsType.AUTOPLAY, ContentSettingsType.IMPORTANT_SITE_INFO, ContentSettingsType.PERMISSION_AUTOBLOCKER_DATA, ContentSettingsType.ADS, ContentSettingsType.ADS_DATA, ContentSettingsType.MIDI, ContentSettingsType.PASSWORD_PROTECTION, ContentSettingsType.MEDIA_ENGAGEMENT, ContentSettingsType.SOUND, ContentSettingsType.CLIENT_HINTS, ContentSettingsType.SENSORS, ContentSettingsType.ACCESSIBILITY_EVENTS, ContentSettingsType.PAYMENT_HANDLER, ContentSettingsType.USB_GUARD, ContentSettingsType.BACKGROUND_FETCH, ContentSettingsType.INTENT_PICKER_DISPLAY, ContentSettingsType.IDLE_DETECTION, ContentSettingsType.SERIAL_GUARD, ContentSettingsType.SERIAL_CHOOSER_DATA, ContentSettingsType.PERIODIC_BACKGROUND_SYNC, ContentSettingsType.BLUETOOTH_SCANNING, ContentSettingsType.HID_GUARD, ContentSettingsType.HID_CHOOSER_DATA, ContentSettingsType.WAKE_LOCK_SCREEN, ContentSettingsType.WAKE_LOCK_SYSTEM, ContentSettingsType.LEGACY_COOKIE_ACCESS, ContentSettingsType.FILE_SYSTEM_WRITE_GUARD, ContentSettingsType.INSTALLED_WEB_APP_METADATA, ContentSettingsType.NFC, ContentSettingsType.BLUETOOTH_CHOOSER_DATA, ContentSettingsType.CLIPBOARD_READ_WRITE, ContentSettingsType.CLIPBOARD_SANITIZED_WRITE, ContentSettingsType.SAFE_BROWSING_URL_CHECK_DATA, ContentSettingsType.VR, ContentSettingsType.AR, ContentSettingsType.FILE_SYSTEM_READ_GUARD, ContentSettingsType.STORAGE_ACCESS, ContentSettingsType.CAMERA_PAN_TILT_ZOOM, ContentSettingsType.WINDOW_PLACEMENT, ContentSettingsType.INSECURE_PRIVATE_NETWORK, ContentSettingsType.FONT_ACCESS, ContentSettingsType.PERMISSION_AUTOREVOCATION_DATA, ContentSettingsType.FILE_SYSTEM_LAST_PICKED_DIRECTORY, ContentSettingsType.DISPLAY_CAPTURE, ContentSettingsType.FILE_HANDLING, ContentSettingsType.FILE_SYSTEM_ACCESS_CHOOSER_DATA, ContentSettingsType.FEDERATED_IDENTITY_SHARING, ContentSettingsType.FEDERATED_IDENTITY_REQUEST, ContentSettingsType.JAVASCRIPT_JIT, ContentSettingsType.HTTP_ALLOWED, ContentSettingsType.FORMFILL_METADATA, ContentSettingsType.FEDERATED_IDENTITY_ACTIVE_SESSION, ContentSettingsType.AUTO_DARK_WEB_CONTENT, ContentSettingsType.NUM_TYPES">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
-            line="194"
-            column="37"/>
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteDataCleaner.java"
+            line="34"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                            0, new VisualStateCallback() {"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java"
-            line="148"
-            column="36"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="111"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                        &amp;&amp; mOverlayPanelManager.get().getActivePanel() != null) {"
-        errorLine2="                                                      ~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java"
-            line="235"
-            column="55"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="160"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                    mOverlayPanelManager.get().getActivePanel().closePanel("
-        errorLine2="                                               ~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java"
-            line="239"
-            column="48"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="162"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        BrowserImplJni.get().addTab(mNativeBrowser, tab.getNativeTab());"
-        errorLine2="                                                        ~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java"
-            line="315"
-            column="57"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="162"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        BrowserImplJni.get().setActiveTab(mNativeBrowser, tab != null ? tab.getNativeTab() : 0);"
-        errorLine2="                                                                            ~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java"
-            line="426"
-            column="77"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="193"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mPartnerBrowserRefreshNeeded = !PartnerBrowserCustomizations.getInstance().isInitialized();"
-        errorLine2="                                                                                   ~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java"
-            line="372"
-            column="84"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="198"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        IntentHandler.setTestIntentsEnabled("
-        errorLine2="                      ~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java"
-            line="762"
-            column="23"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="205"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        DownloadManagerService.getDownloadManagerService().onDownloadFailed(downloadItem, reason);"
-        errorLine2="                                                           ~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java"
-            line="184"
-            column="60"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="211"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mOverviewListLayout = (OverviewListLayout) mLayoutManager.getOverviewListLayout();"
-        errorLine2="                                                                  ~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java"
-            line="803"
-            column="67"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="217"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                IconProvider.getIcon(context, R.drawable.infobar_autofill_cc),"
-        errorLine2="                             ~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetCoordinator.java"
-            line="37"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                    webappActivity.getIntentDataProvider();"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java"
-            line="260"
-            column="36"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mConnection.cleanUpSession(sessionToken);"
-        errorLine2="                    ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionServiceImpl.java"
-            line="104"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                mDownloadNotificationService.notifyDownloadPaused(entry.id, entry.fileName, true,"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManagerImpl.java"
-            line="138"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                mDownloadNotificationService.notifyDownloadCanceled(entry.id, true);"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManagerImpl.java"
-            line="144"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        Set&lt;String> entries = DownloadManagerService.getStoredDownloadInfo("
-        errorLine2="                                                     ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceHelper.java"
-            line="134"
-            column="54"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            EditorTextField inputLayout = new EditorTextField("
-        errorLine2="                                          ^">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java"
-            line="494"
-            column="43"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            EditText input = inputLayout.getEditText();"
-        errorLine2="                                         ~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java"
-            line="498"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                            ImageFetcher.resizeImage(bitmap, params.width, params.height));"
-        errorLine2="                                         ~~~~~~~~~~~">
-        <location
-            file="../../components/image_fetcher/android/java/src/org/chromium/components/image_fetcher/ImageFetcherBridge.java"
-            line="92"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                                IncognitoNotificationServiceImpl.getRemoveAllIncognitoTabsIntent("
-        errorLine2="                                                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationManager.java"
-            line="56"
-            column="66"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            ClickableSpan[] spans = getClickableSpans();"
-        errorLine2="                                    ~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/infobars/android/java/src/org/chromium/components/infobars/InfoBarMessageView.java"
-            line="39"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                assert mExternalNavHandler.canExternalAppHandleUrl(url);"
-        errorLine2="                                           ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java"
-            line="142"
-            column="44"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        int resId = mExternalNavHandler.canExternalAppHandleUrl(url)"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java"
-            line="286"
-            column="41"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        } else if (animationsEnabled()) {"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
-            line="117"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        boolean animate = !tabRemoved &amp;&amp; animationsEnabled();"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
-            line="136"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        } else if (animationsEnabled()) {"
-        errorLine2="                   ~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
-            line="150"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                    ((ChromeTabbedActivity) activity).saveState();"
-        errorLine2="                                                      ~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java"
-            line="373"
-            column="55"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                NavigationControllerImplJni.get().getNavigationController(tab.getNativeTab());"
-        errorLine2="                                                                              ~~~~~~~~~~~~">
-        <location
-            file="../../weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java"
-            line="41"
-            column="79"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                NewTabCallbackProxyJni.get().createNewTabCallbackProxy(this, tab.getNativeTab());"
-        errorLine2="                                                                                 ~~~~~~~~~~~~">
-        <location
-            file="../../weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java"
-            line="26"
-            column="82"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="230"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                mNewTabPageLayout.getTileGroup().onSwitchToForeground(/* trackLoadTask = */ false);"
-        errorLine2="                                  ~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java"
-            line="313"
-            column="35"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="231"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return DownloadManagerService.getStoredDownloadInfo(sharedPrefs, type);"
-        errorLine2="                                      ~~~~~~~~~~~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ScrollDirection.LEFT, ScrollDirection.RIGHT, ScrollDirection.UP, ScrollDirection.DOWN">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java"
-            line="902"
-            column="39"/>
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java"
+            line="231"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return VersionNumberGetter.getInstance().getCurrentlyUsedVersion(getContext());"
-        errorLine2="                                   ~~~~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: FocusState.NOT_APPLICABLE, FocusState.VIEW_FOCUSED_WITHOUT_WINDOW_FOCUS, FocusState.VIEW_FOCUSED_THEN_WINDOW_FOCUSED">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java"
-            line="321"
-            column="36"/>
+            file="../../content/public/android/java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java"
+            line="282"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            String appId = getRequestGenerator().getAppId();"
-        errorLine2="                                                 ~~~~~~~~">
+        id="WrongConstant"
+        message="Must be one of: ImageFormat.UNKNOWN, ImageFormat.RGB_565, ImageFormat.YV12, ImageFormat.Y8, ImageFormat.NV16, ImageFormat.NV21, ImageFormat.YUY2, ImageFormat.JPEG, ImageFormat.DEPTH_JPEG, ImageFormat.YUV_420_888, ImageFormat.YUV_422_888, ImageFormat.YUV_444_888, ImageFormat.FLEX_RGB_888, ImageFormat.FLEX_RGBA_8888, ImageFormat.RAW_SENSOR, ImageFormat.RAW_PRIVATE, ImageFormat.RAW10, ImageFormat.RAW12, ImageFormat.DEPTH16, ImageFormat.DEPTH_POINT_CLOUD, ImageFormat.PRIVATE, ImageFormat.HEIC">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java"
-            line="349"
-            column="50"/>
+            file="../../media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java"
+            line="1074"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                            .setAnchorView(mToolbarLayout.getOptionalButtonView())"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~~~~~~~">
+        id="CustomSplashScreen"
+        message="The application should not provide its own launch screen">
         <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/OptionalBrowsingModeButtonController.java"
-            line="114"
-            column="59"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/browserservices/ui/splashscreen/SplashscreenObserver.java"
+            line="10"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            mContent.destroy();"
-        errorLine2="                     ~~~~~~~">
+        id="CustomSplashScreen"
+        message="The application should not provide its own launch screen">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java"
-            line="516"
-            column="22"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkSplashscreenMetrics.java"
+            line="14"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        if (!browserCustomizations.isInitialized()) {"
-        errorLine2="                                   ~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java"
-            line="102"
-            column="36"/>
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/CrashesListFragment.java"
+            line="502"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                IconProvider.getIcon(context, R.drawable.ic_vpn_key_grey),"
-        errorLine2="                             ~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessorySheetCoordinator.java"
-            line="43"
-            column="30"/>
+            file="../../chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAState.java"
+            line="238"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        getTab().setIcon(IconProvider.getIcon("
-        errorLine2="                                      ~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessorySheetCoordinator.java"
-            line="66"
-            column="39"/>
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/webapps/launchpad/LaunchpadUtils.java"
+            line="60"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        String distillerUrl = DomDistillerUrlUtils.getDistillerViewUrlFromUrl("
-        errorLine2="                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java"
-            line="471"
-            column="52"/>
+            file="../../components/permissions/android/java/src/org/chromium/components/permissions/nfc/NfcSystemLevelSetting.java"
+            line="86"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                new SettingsSecureBasedIdentificationGenerator(getContext()), false);"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java"
-            line="43"
-            column="17"/>
+            file="../../components/payments/content/android/java/src/org/chromium/components/payments/PackageManagerDelegate.java"
+            line="96"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                new SettingsSecureBasedIdentificationGenerator(ContextUtils.getApplicationContext())"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java"
-            line="40"
-            column="17"/>
+            file="../../base/android/java/src/org/chromium/base/PackageManagerUtils.java"
+            line="56"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mSearchBox.beginQuery(isVoiceSearchIntent(), getOptionalIntentQuery());"
-        errorLine2="                   ~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java"
-            line="341"
-            column="20"/>
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java"
+            line="406"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        Intent intent = getShareLinkIntent(params);"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java"
-            line="67"
-            column="25"/>
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java"
+            line="407"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            ShareHelper.setLastShareComponentName(component);"
-        errorLine2="                        ~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
             file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java"
-            line="212"
-            column="25"/>
+            line="254"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within package private scope"
-        errorLine1="        SigninPreferencesManager.getInstance().setNewTabPageSigninPromoSuppressionPeriodStart("
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
-            line="110"
-            column="48"/>
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java"
+            line="260"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within package private scope"
-        errorLine1="                                      .getNewTabPageSigninPromoSuppressionPeriodStart();"
-        errorLine2="                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
-            line="124"
-            column="40"/>
+            file="../../content/public/android/java/src/org/chromium/content/browser/SpeechRecognitionImpl.java"
+            line="198"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within package private scope"
-        errorLine1="        SigninPreferencesManager.getInstance().clearNewTabPageSigninPromoSuppressionPeriodStart();"
-        errorLine2="                                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
-            line="131"
-            column="48"/>
+            file="../../components/webapk/android/libs/client/src/org/chromium/components/webapk/lib/client/WebApkValidator.java"
+            line="157"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                &amp;&amp; clickedTab.getVisiblePercentage() >= 1.f"
-        errorLine2="                              ~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java"
-            line="802"
-            column="31"/>
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/WebViewPackageError.java"
+            line="152"/>
     </issue>
 
     <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                requestId, new AwContents.VisualStateCallback() {"
-        errorLine2="                               ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="QueryPermissionsNeeded"
+        message="Consider adding a `&lt;queries>` declaration to your manifest when calling this \&#xA;method; see https://g.co/dev/packagevisibility for details">
         <location
-            file="../../android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java"
-            line="50"
-            column="32"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        assert AccountUtils.GOOGLE_ACCOUNT_TYPE.equals(account.type);"
-        errorLine2="                            ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/signin/public/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java"
-            line="141"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        getDownloadNotificationService().notifyDownloadCanceled(id, false);"
-        errorLine2="                                         ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="122"
-            column="42"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                getDownloadNotificationService().notifyDownloadProgress(info.getContentId(),"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="243"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                getDownloadNotificationService().notifyDownloadPaused(info.getContentId(),"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="251"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                        getDownloadNotificationService().notifyDownloadSuccessful("
-        errorLine2="                                                         ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="258"
-            column="58"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                getDownloadNotificationService().notifyDownloadFailed(info.getContentId(),"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="273"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                getDownloadNotificationService().notifyDownloadPaused(info.getContentId(),"
-        errorLine2="                                                 ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
-            line="278"
-            column="50"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mTileRenderer.renderTileSection(tiles, mSectionView, mTileGroup.getTileSetupDelegate());"
-        errorLine2="                                                                        ~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/TileGridViewHolder.java"
-            line="34"
-            column="73"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                                != mTabSwitcherAnimationTabStackDrawable.getTabCount();"
-        errorLine2="                                                                         ~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java"
-            line="1548"
-            column="74"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        return mToolbarLayout.getLocationBar();"
-        errorLine2="                              ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java"
-            line="610"
-            column="31"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                        VersionNumberGetter.getInstance().getLatestKnownVersion(context);"
-        errorLine2="                                            ~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateStatusProvider.java"
-            line="423"
-            column="45"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        mWebApkUpdateManager.get().updateIfNeeded(storage, mActivity.getIntentDataProvider());"
-        errorLine2="                                                                     ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkActivityCoordinator.java"
-            line="56"
-            column="70"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                requestId, callback == null ? null : new AwContents.VisualStateCallback() {"
-        errorLine2="                                                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java"
-            line="971"
-            column="58"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                mAwContents.getWebContents()));"
-        errorLine2="                            ~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java"
-            line="1827"
-            column="29"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="            WebappExtras webappExtras = customTabActivity.getIntentDataProvider().getWebappExtras();"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLocator.java"
-            line="44"
-            column="59"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        list.add(new StorageInfo(host, type, size));"
-        errorLine2="                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
-            line="70"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="                .put(origin, new LocalStorageInfo(origin, size, important));"
-        errorLine2="                             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
-            line="88"
-            column="30"/>
-    </issue>
-
-    <issue
-        id="VisibleForTests"
-        message="This method should only be accessed from tests or within private scope"
-        errorLine1="        list.add(new ChosenObjectInfo("
-        errorLine2="                 ^">
-        <location
-            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
-            line="143"
-            column="18"/>
-    </issue>
-
-    <issue
-        id="UseAppTint"
-        message="Must use `app:tint` instead of `android:tint`"
-        errorLine1="        android:tint=&quot;@color/default_icon_color_blue&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/messages/android/java/res/layout/message_banner_view.xml"
-            line="29"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="UseAppTint"
-        message="Must use `app:tint` instead of `android:tint`"
-        errorLine1="            android:tint=&quot;@color/photo_picker_tile_bg_color&quot; />"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_bitmap_view.xml"
-            line="109"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseAppTint"
-        message="Must use `app:tint` instead of `android:tint`"
-        errorLine1="            android:tint=&quot;@color/default_icon_color&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/search_widget_template.xml"
-            line="42"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseAppTint"
-        message="Must use `app:tint` instead of `android:tint`"
-        errorLine1="                android:tint=&quot;@color/ungroup_bar_shadow_color&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/features/tab_ui/java/res/layout/tab_grid_dialog_layout.xml"
-            line="35"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="UseAppTint"
-        message="Must use `app:tint` instead of `android:tint`"
-        errorLine1="            android:tint=&quot;@color/default_icon_color&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/tab_switcher_toolbar.xml"
-            line="29"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseCompatLoadingForDrawables"
-        message="Use `ResourcesCompat.getDrawable()`"
-        errorLine1="                return res.getDrawable(id, null);"
-        errorLine2="                       ~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java"
-            line="364"
-            column="24"/>
-    </issue>
-
-    <issue
-        id="UseCompatLoadingForDrawables"
-        message="Use `ResourcesCompat.getDrawable()`"
-        errorLine1="            Drawable mInlineTitleIcon = resources.getDrawable(googlePayDrawableId);"
-        errorLine2="                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/CardUnmaskPrompt.java"
-            line="195"
-            column="41"/>
-    </issue>
-
-    <issue
-        id="UseCompatLoadingForDrawables"
-        message="Use `ResourcesCompat.getDrawable()`"
-        errorLine1="        Drawable clearTextIcon = getResources().getDrawable(R.drawable.ic_clear_text);"
-        errorLine2="                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
-            line="152"
-            column="34"/>
-    </issue>
-
-    <issue
-        id="UseCompatLoadingForDrawables"
-        message="Use `AppCompatResources.getDrawable()`"
-        errorLine1="                view.setForeground(view.getContext().getDrawable(R.drawable.piet_clickable_ripple));"
-        errorLine2="                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ViewUtils.java"
-            line="60"
-            column="36"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="            android:drawableTop=&quot;@drawable/ic_action_home&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/res_devui/layout/activity_main.xml"
-            line="50"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="            android:drawableTop=&quot;@drawable/ic_alert_error&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/res_devui/layout/activity_main.xml"
-            line="60"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="            android:drawableTop=&quot;@drawable/ic_flag&quot;"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/res_devui/layout/activity_main.xml"
-            line="70"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableEndCompat` instead of `android:drawableEnd`"
-        errorLine1="                android:drawableEnd=&quot;@drawable/data_reduction_breakdown_sort_arrow&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/data_usage_breakdown.xml"
-            line="48"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableStartCompat` instead of `android:drawableStart`"
-        errorLine1="                android:drawableStart=&quot;@drawable/data_reduction_breakdown_sort_arrow&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/data_usage_breakdown.xml"
-            line="58"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableStartCompat` instead of `android:drawableStart`"
-        errorLine1="                android:drawableStart=&quot;@drawable/data_reduction_breakdown_sort_arrow&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/data_usage_breakdown.xml"
-            line="69"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableEndCompat` instead of `android:drawableEnd`"
-        errorLine1="    android:drawableEnd=&quot;@drawable/exclamation_triangle&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/os_version_unsupported_text.xml"
-            line="15"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableStartCompat` instead of `android:drawableStart`"
-        errorLine1="        android:drawableStart=&quot;@drawable/ic_alert_error&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/res_devui/layout/persistent_error_message.xml"
-            line="26"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableStartCompat` instead of `android:drawableStart`"
-        errorLine1="        android:drawableStart=&quot;@drawable/ic_error&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/qrcode_camera_error_layout.xml"
-            line="27"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="                    android:drawableTop=&quot;@drawable/edit_icon&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="49"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTint` instead of `android:drawableTint`"
-        errorLine1="                    android:drawableTint=&quot;@color/default_icon_color_tint_list&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="50"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="                    android:drawableTop=&quot;@drawable/delete_icon&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="60"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTint` instead of `android:drawableTint`"
-        errorLine1="                    android:drawableTint=&quot;@color/default_icon_color_tint_list&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="61"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="                    android:drawableTop=&quot;@drawable/save_icon&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="71"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTint` instead of `android:drawableTint`"
-        errorLine1="                    android:drawableTint=&quot;@color/default_icon_color_tint_list&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="72"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTopCompat` instead of `android:drawableTop`"
-        errorLine1="                    android:drawableTop=&quot;@drawable/share_icon&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="82"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompatTextViewDrawableXml"
-        message="Use `app:drawableTint` instead of `android:drawableTint`"
-        errorLine1="                    android:drawableTint=&quot;@color/default_icon_color_tint_list&quot;"
-        errorLine2="                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml"
-            line="83"
-            column="21"/>
-    </issue>
-
-    <issue
-        id="UseCompoundDrawables"
-        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
-        errorLine1="        &lt;LinearLayout"
-        errorLine2="         ~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_bitmap_view.xml"
-            line="37"
-            column="10"/>
-    </issue>
-
-    <issue
-        id="UseCompoundDrawables"
-        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
-        errorLine1="    &lt;LinearLayout"
-        errorLine2="     ~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_bitmap_view.xml"
-            line="94"
-            column="6"/>
-    </issue>
-
-    <issue
-        id="UseCompoundDrawables"
-        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable"
-        errorLine1="  &lt;LinearLayout"
-        errorLine2="   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/share/android/java/res/layout/qrcode_camera_error_layout.xml"
-            line="11"
-            column="4"/>
-    </issue>
-
-    <issue
-        id="MergeRootFrame"
-        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
-        errorLine1="&lt;FrameLayout"
-        errorLine2="^">
-        <location
-            file="../../chrome/android/feed/core/java/resv1/layout/feed_more_button.xml"
-            line="7"
-            column="1"/>
-    </issue>
-
-    <issue
-        id="MergeRootFrame"
-        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag"
-        errorLine1="&lt;FrameLayout"
-        errorLine2="^">
-        <location
-            file="../../chrome/android/java/res/layout/signin_activity.xml"
-            line="5"
-            column="1"/>
-    </issue>
-
-    <issue
-        id="UseSparseArrays"
-        message="Use `new SparseBooleanArray(...)` instead for better performance"
-        errorLine1="        mGroupsCollapsedState = new SparseArray&lt;>();"
-        errorLine2="                                ~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/DropdownItemViewInfoListManager.java"
-            line="35"
-            column="33"/>
-    </issue>
-
-    <issue
-        id="UsableSpace"
-        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data"
-        errorLine1="                    dir.getAbsolutePath(), dir.getUsableSpace(), dir.getTotalSpace(), type);"
-        errorLine2="                                               ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java"
-            line="152"
-            column="48"/>
-    </issue>
-
-    <issue
-        id="UsableSpace"
-        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data"
-        errorLine1="            mFreeSpace = Environment.getExternalStorageDirectory().getUsableSpace();"
-        errorLine2="                                                                   ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java"
-            line="317"
-            column="68"/>
-    </issue>
-
-    <issue
-        id="UsableSpace"
-        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data"
-        errorLine1="        return Environment.getDataDirectory().getUsableSpace();"
-        errorLine2="                                              ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java"
-            line="241"
-            column="47"/>
-    </issue>
-
-    <issue
-        id="UsableSpace"
-        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data"
-        errorLine1="                        defaultDownloadDir.getAbsolutePath(), defaultDownloadDir.getUsableSpace(),"
-        errorLine2="                                                                                 ~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java"
-            line="86"
-            column="82"/>
-    </issue>
-
-    <issue
-        id="Autofill"
-        message="Missing `autofillHints` attribute"
-        errorLine1="        &lt;EditText"
-        errorLine2="         ~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/res_devui/layout/fragment_flags.xml"
-            line="25"
-            column="10"/>
-    </issue>
-
-    <issue
-        id="Autofill"
-        message="Missing `autofillHints` attribute"
-        errorLine1="            &lt;EditText"
-        errorLine2="             ~~~~~~~~">
-        <location
-            file="../../chrome/browser/password_check/android/java/res/layout/password_check_edit_fragment.xml"
-            line="31"
-            column="14"/>
-    </issue>
-
-    <issue
-        id="Autofill"
-        message="Missing `autofillHints` attribute"
-        errorLine1="            &lt;EditText"
-        errorLine2="             ~~~~~~~~">
-        <location
-            file="../../chrome/browser/password_check/android/java/res/layout/password_check_edit_fragment.xml"
-            line="52"
-            column="14"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `AccessibilityTabModelListItem` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent e) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java"
-            line="458"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="            row.setDragHandleOnTouchListener((v, event) -> {"
-        errorLine2="                                             ^">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
-            line="216"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        mDragHandle.setOnTouchListener(l);"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java"
-            line="292"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `BottomSheet` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent e) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java"
-            line="278"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``TextView`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="                textView.setOnTouchListener(new ChunkedTextTouchListener(spannable));"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ChunkedTextElementAdapter.java"
-            line="159"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`ChunkedTextTouchListener#onTouch` should call `View#performClick` when a click is detected"
-        errorLine1="        public boolean onTouch(View widget, MotionEvent event) {"
-        errorLine2="                       ~~~~~~~">
-        <location
-            file="../../chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ChunkedTextElementAdapter.java"
-            line="383"
-            column="24"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``TextView`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        textView.setOnTouchListener((View v, MotionEvent event) -> {"
-        errorLine2="        ^">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataCheckBoxPreference.java"
-            line="54"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="        textView.setOnTouchListener((View v, MotionEvent event) -> {"
-        errorLine2="                                    ^">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataCheckBoxPreference.java"
-            line="54"
-            column="37"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `CompositorViewHolder` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent e) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java"
-            line="670"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `ContentView` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java"
-            line="333"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``ImageButton`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        menuBtn.setOnTouchListener(menuPopupButtonHelper);"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewTablet.java"
-            line="98"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``EditText`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="            editText.setOnTouchListener((View v, MotionEvent event) -> {"
-        errorLine2="            ^">
-        <location
-            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
-            line="165"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="            editText.setOnTouchListener((View v, MotionEvent event) -> {"
-        errorLine2="                                        ^">
-        <location
-            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
-            line="165"
-            column="41"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``EditText`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="            editText.setOnTouchListener(null);"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
-            line="180"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `FullScreenView` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(final MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../android_webview/java/src/org/chromium/android_webview/FullScreenView.java"
-            line="91"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `InfoBarMessageView` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/infobars/android/java/src/org/chromium/components/infobars/InfoBarMessageView.java"
-            line="32"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        holder.mStartIcon.setOnTouchListener((v, event) -> {"
-        errorLine2="        ^">
-        <location
-            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
-            line="173"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="        holder.mStartIcon.setOnTouchListener((v, event) -> {"
-        errorLine2="                                             ^">
-        <location
-            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
-            line="173"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `LocationBarTablet` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarTablet.java"
-            line="135"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``ImageButton`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        mMenuImageButton.setOnTouchListener(mAppMenuButtonHelper);"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java"
-            line="77"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="        View.OnTouchListener onTouchListener = (View v, MotionEvent ev) -> {"
-        errorLine2="                                               ^">
-        <location
-            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
-            line="206"
-            column="48"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        positiveButton.setOnTouchListener(onTouchListener);"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
-            line="236"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`"
-        errorLine1="        negativeButton.setOnTouchListener(onTouchListener);"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
-            line="238"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `NoSwipeViewPager` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/NoSwipeViewPager.java"
-            line="24"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` should call `View#performClick` when a click is detected"
-        errorLine1="            public boolean onTouch(View v, MotionEvent event) {"
-        errorLine2="                           ~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerVideoPlayer.java"
-            line="230"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `PlayerFrameView` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameView.java"
-            line="107"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `ScrimView` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent e) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/scrim/ScrimView.java"
-            line="79"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` lambda should call `View#performClick` when a click is detected"
-        errorLine1="        mEmptyViewWrapper.setOnTouchListener((v, event) -> true);"
-        errorLine2="                                             ~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java"
-            line="239"
-            column="46"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `ToolbarControlContainer` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java"
-            line="261"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `ToolbarPhone` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent ev) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java"
-            line="503"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="Custom view `TouchRestrictingFrameLayout` overrides `onTouchEvent` but not `performClick`"
-        errorLine1="    public boolean onTouchEvent(MotionEvent event) {"
-        errorLine2="                   ~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/TouchRestrictingFrameLayout.java"
-            line="46"
-            column="20"/>
-    </issue>
-
-    <issue
-        id="ClickableViewAccessibility"
-        message="`onTouch` should call `View#performClick` when a click is detected"
-        errorLine1="            public boolean onTouch(View view, MotionEvent event) {"
-        errorLine2="                           ~~~~~~~">
-        <location
-            file="../../weblayer/browser/java/org/chromium/weblayer_private/WebContentsGestureStateTracker.java"
-            line="48"
-            column="28"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="    android:clickable=&quot;true&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml"
-            line="8"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="                android:clickable=&quot;true&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
-            line="49"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="                android:clickable=&quot;true&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
-            line="73"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="                android:clickable=&quot;true&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
-            line="97"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="        android:clickable=&quot;true&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_dialog.xml"
-            line="38"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="            android:clickable=&quot;true&quot; >"
-        errorLine2="            ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/search_activity.xml"
-            line="28"
-            column="13"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="    android:clickable=&quot;true&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml"
-            line="13"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="    android:clickable=&quot;true&quot; >"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../chrome/android/java/res/layout/tab_switcher_toolbar.xml"
-            line="13"
-            column="5"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="        android:clickable=&quot;true&quot;"
-        errorLine2="        ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
-            line="37"
-            column="9"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="                android:clickable=&quot;true&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
-            line="99"
-            column="17"/>
-    </issue>
-
-    <issue
-        id="KeyboardInaccessibleWidget"
-        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;"
-        errorLine1="                android:clickable=&quot;true&quot;"
-        errorLine2="                ~~~~~~~~~~~~~~~~~~~~~~~~">
-        <location
-            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
-            line="124"
-            column="17"/>
+            file="../../components/webapps/browser/android/java/src/org/chromium/components/webapps/WebappsUtils.java"
+            line="132"/>
     </issue>
 
     <issue
         id="VectorRaster"
-        message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more"
-        errorLine1="    android:width=&quot;360dp&quot;"
-        errorLine2="                   ~~~~~">
+        message="Limit vector icons sizes to 200×200 to keep icon drawing fast; see https://developer.android.com/studio/write/vector-asset-studio#when for more">
         <location
             file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
-            line="7"
-            column="5"/>
+            line="7"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="26"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="31"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="38"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="47"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="55"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="62"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="67"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/adaptive_toolbar_preference_header.xml"
+            line="73"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/address.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/address.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_down.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_down.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_down.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_down.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_down.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_up.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_up.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_up.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_up.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/arrow_up.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/async_image_view_unavailable.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/async_image_view_unavailable.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/async_image_view_unavailable.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/feed/android/java/res/drawable/back_to_top_arrow.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/camera_img.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/multiwindow/java/res/drawable/checkmark_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/checkmark_blue.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/checkmark_blue.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/checkmark_blue.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/webauthn/android/java/res/drawable/circle_loader.xml"
+            line="30"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/webauthn/android/java/res/drawable/circle_loader.xml"
+            line="42"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/webauthn/android/java/res/drawable/circle_loader.xml"
+            line="54"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/webauthn/android/java/res/drawable/circle_loader.xml"
+            line="63"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/computer_black_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/data_reduction_big.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/data_reduction_big.xml"
+            line="22"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/delete_icon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/delete_icon.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/devices_black_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/edit_icon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/edit_icon.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/email.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/face.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/generic_favicon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/generic_favicon.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/generic_file.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/generic_file.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_20.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_20.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_20.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_20.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_24.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_bluetooth_searching_24.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_cardboard_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_cardboard_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_cardboard_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_cardboard_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_content_paste_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_content_paste_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_content_paste_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_content_paste_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_devices_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_devices_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_devices_20.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_devices_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_devices_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_location_off_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_location_off_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_location_off_24.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_location_on_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_location_on_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_location_on_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_location_on_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_20.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_mic_24.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_mic_off_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_mic_off_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_nfc_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_nfc_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_nfc_20.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_nfc_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_nfc_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_20.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_notifications_24.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_notifications_off_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_notifications_off_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_piano_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_piano_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_piano_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_piano_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_usb_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_usb_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_usb_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_usb_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_videocam_20.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_videocam_20.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_videocam_24.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/gm_filled_videocam_24.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_videocam_off_24.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_videocam_off_24.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/android/webapps/launchpad/java/res/drawable/gm_filled_videocam_off_24.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/payments/content/android/minimal_java_res/drawable/google_pay.xml"
+            line="28"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/payments/content/android/minimal_java_res/drawable/google_pay.xml"
+            line="31"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/payments/content/android/minimal_java_res/drawable/google_pay.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable-ldrtl/google_pay_with_divider.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/google_pay_with_divider.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable-ldrtl/google_pay_with_divider.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/google_pay_with_divider.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable-ldrtl/google_pay_with_divider.xml"
+            line="24"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/google_pay_with_divider.xml"
+            line="24"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable-ldrtl/google_pay_with_divider.xml"
+            line="40"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/google_pay_with_divider.xml"
+            line="40"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_add_alert_blue.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_add_box_rounded_corner.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_add_box_rounded_corner.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_add_to_home_screen.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../ui/android/java/res/drawable/ic_apps_blue_24dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res-arcore/drawable/ic_ar_core_install.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_arrow_back_24dp.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_arrow_back_24dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_arrow_back_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_arrow_forward_blue_24dp.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_arrow_forward_blue_24dp.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_auto_awesome.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_add_circle_24dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/password_check/android/internal/java/res/drawable/ic_autofill_assistant_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/password_check/android/internal/java/res/drawable/ic_autofill_assistant_white_24dp.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/password_check/android/internal/java/res/drawable/ic_autofill_assistant_white_24dp.xml"
+            line="22"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/password_check/android/internal/java/res/drawable/ic_autofill_assistant_white_24dp.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_block_red.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_bluetooth_connected.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_book_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_book_round.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_book_round.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_brightness_medium_20dp.xml"
+            line="6"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_brightness_medium_20dp.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_brightness_medium_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_business.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_cancel_circle.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/password_check/android/internal/java/res/drawable/ic_check_circle_filled_green_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_checkmark_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_collections_grey.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_content_copy_black.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_data_viz_grey.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../android_webview/nonembedded/java/res_devui/drawable/ic_delete.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_desktop_windows.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/ic_dino.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_done_blue.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_equals_sign_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_equals_sign_round.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_error.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_event_round.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/signin/ui/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/signin/ui/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_eye_crossed.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_file_download_scheduled_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_file_download_scheduled_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_file_download_scheduled_24dp.xml"
+            line="20"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_file_download_scheduled_24dp.xml"
+            line="24"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_file_download_scheduled_24dp.xml"
+            line="27"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_find_in_page.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_folder_blue_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_forward_arrow_black_24dp.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_full_screen_exit_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_full_screen_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_google_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_google_services_48dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_group_icon_16dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_help_and_feedback.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_help_and_feedback.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_help_and_feedback.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_image_descriptions.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_image_descriptions.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_incognito_cct_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_incognito_cct_24dp.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_incognito_cct_24dp.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_info_outline_grey_16dp.xml"
+            line="20"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_info_outline_grey_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_loop_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_loop_round.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_new_window.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_new_window.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_offer_tag.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_offline_pin_24dp_on_dark_bg.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_offline_pin_24dp_on_dark_bg.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_offline_pin_24dp_on_light_bg.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_offline_pin_24dp_on_light_bg.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_offline_pin_blue_white.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_offline_pin_blue_white.xml"
+            line="20"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_offline_pin_white.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_offline_pin_white.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_open_in_browser.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/res/drawable/ic_overflow_black_24dp.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_pause_circle_outline_white_24dp.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_pause_circle_outline_white_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/site_settings/android/java/res/drawable/ic_person_24dp.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_person_add_40dp.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_photo_camera_black.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_photo_camera_black.xml"
+            line="24"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_photo_camera_grey.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_photo_camera_grey.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_play_circle_filled_24dp_on_dark_bg.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_play_circle_filled_24dp_on_dark_bg.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_play_circle_filled_24dp_on_light_bg.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_play_circle_filled_24dp_on_light_bg.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_play_circle_filled_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/ic_play_circle_filled_white_24dp.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_rating_star_full.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_rating_star_half.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_rating_star_outline.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_reading_list_folder_24dp.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_remove_box_rounded_corner.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_remove_box_rounded_corner.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_security_grey.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_select_window.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/widget/android/java/res/drawable/ic_settings_gear_24dp.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_0_bar.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_1_bar.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_1_bar.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_2_bar.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_2_bar.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_3_bar.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_3_bar.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/permissions/android/res/drawable/ic_signal_cellular_4_bar.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_signout_40dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_site_timer.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_swap_vert_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_swap_vert_round.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_badge_error_20dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_badge_error_20dp.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_badge_error_20dp.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_error_48dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_error_48dp.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_error_legacy_40dp.xml"
+            line="20"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_off_48dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_off_48dp.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_on_48dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_sync_on_48dp.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_touch_app_blue.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_translate.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_trending_down_black.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/ic_trending_down_blue.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_tune_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_tv_options_input_settings_rotated_grey.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_update_grey.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_volume_off_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_volume_on_white_24dp.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_vpn_key_blue.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_vpn_key_grey.xml"
+            line="4"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_warning_red_16dp.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/ic_warning_red_24dp.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_wb_sunny_round.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/ic_wb_sunny_round.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/ic_widgets.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="26"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="27"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="30"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="33"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="40"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="43"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="52"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="58"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="63"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="66"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/incognito_history_placeholder_image.xml"
+            line="69"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/infobar_download_complete.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/infobar_download_complete.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/ink_highlighter.xml"
+            line="6"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/ink_highlighter.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/iph_drag_and_drop_drawable.xml"
+            line="64"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/iph_drag_and_drop_drawable.xml"
+            line="79"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/lightweight_reactions_icon.xml"
+            line="6"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/lightweight_reactions_icon.xml"
+            line="7"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/lightweight_reactions_icon.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/link.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/link_off.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/link_off.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml"
+            line="29"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml"
+            line="33"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_partly_cloudy.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/logo_translate_round.xml"
+            line="29"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/long_screenshot.xml"
+            line="10"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/long_screenshot.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/long_screenshot.xml"
+            line="22"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/long_screenshot.xml"
+            line="28"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/names.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/price_tracking_disabled.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/price_tracking_enabled.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="27"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="33"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="40"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="47"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/qr_code.xml"
+            line="54"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="9"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="22"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="26"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="30"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="34"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="38"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="42"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="46"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="50"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="54"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="57"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="64"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="70"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="76"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="82"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="88"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="94"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="100"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="106"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="112"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="118"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="124"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="130"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="136"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="142"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="148"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/quickactionsearchwidget/java/res/drawable/quick_action_search_widget_dino_content.xml"
+            line="154"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/save_icon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/save_icon.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/save_to_device.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/screenshot.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/screenshot.xml"
+            line="23"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/screenshot.xml"
+            line="29"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/screenshot.xml"
+            line="35"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/screenshot.xml"
+            line="41"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/send_tab.xml"
+            line="14"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/send_tab.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/site_settings/android/java/res/drawable/settings_bluetooth.xml"
+            line="4"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/share_icon.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/sharing_more.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/sharing_more.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/sharing_more.xml"
+            line="22"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/sharing_print.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/java/res/drawable/sharing_print.xml"
+            line="15"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/styles/android/java/res/drawable/smartphone_black_24dp.xml"
+            line="17"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/switch_to_tab.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/ui/android/omnibox/java/res/drawable/switch_to_tab.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring_incognito.xml"
+            line="12"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring_incognito.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/android/features/tab_ui/java/res/drawable/tab_strip_selected_ring_incognito.xml"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/drawable/telephone.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable-ldrtl/text_icon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/text_icon.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/feed/android/java/res/drawable/web_feed_post_follow_illustration.xml"
+            line="5"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/feed/android/java/res/drawable/web_feed_post_follow_illustration.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/webnote.xml"
+            line="6"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../chrome/browser/share/android/java/res/drawable/webnote.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/zoom_in.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/zoom_in.xml"
+            line="16"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/zoom_in.xml"
+            line="21"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/zoom_out.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="VectorRaster"
+        message="">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/drawable/zoom_out.xml"
+            line="18"/>
+    </issue>
+
+    <issue
+        id="UnsupportedChromeOsCameraSystemFeature"
+        message="You should look for any camera available on the device, not just the rear">
+        <location
+            file="../../base/android/java/src/org/chromium/base/SysUtils.java"
+            line="160"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/AddressAccessorySheetCoordinator.java"
+            line="39"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/payments/content/android/java/src/org/chromium/components/payments/AndroidPaymentAppFinder.java"
+            line="555"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java"
+            line="392"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java"
+            line="83"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/additional_sections/AssistantTextInputSection.java"
+            line="146"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantViewFactory.java"
+            line="145"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/generic_ui/AssistantViewInteractions.java"
+            line="108"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/tab/AuthenticatorNavigationInterceptorTabHelper.java"
+            line="19"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwBrowserProcess.java"
+            line="152"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
+            line="1451"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
+            line="1968"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwContents.java"
+            line="2946"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java"
+            line="172"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwContentsStatics.java"
+            line="172"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
+            line="34"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
+            line="186"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
+            line="190"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsDelegateAdapter.java"
+            line="194"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/AwWebContentsObserver.java"
+            line="251"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java"
+            line="312"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/BottomSheetManager.java"
+            line="313"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java"
+            line="349"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/BrowserImpl.java"
+            line="460"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java"
+            line="466"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java"
+            line="955"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/ChromeDownloadDelegate.java"
+            line="184"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java"
+            line="908"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/CreditCardAccessorySheetCoordinator.java"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionServiceImpl.java"
+            line="104"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManagerImpl.java"
+            line="141"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadBroadcastManagerImpl.java"
+            line="155"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSharedPreferenceHelper.java"
+            line="134"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java"
+            line="515"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/autofill/prefeditor/EditorDialog.java"
+            line="519"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/image_fetcher/android/java/src/org/chromium/components/image_fetcher/ImageFetcherBridge.java"
+            line="95"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationManager.java"
+            line="55"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/infobars/android/java/src/org/chromium/components/infobars/InfoBarMessageView.java"
+            line="39"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java"
+            line="146"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/external_intents/android/java/src/org/chromium/components/external_intents/InterceptNavigationDelegateImpl.java"
+            line="304"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
+            line="112"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
+            line="132"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java"
+            line="146"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManager.java"
+            line="428"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/NavigationControllerImpl.java"
+            line="49"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/NewTabCallbackProxy.java"
+            line="26"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java"
+            line="349"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java"
+            line="893"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java"
+            line="320"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/OmahaBase.java"
+            line="348"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/OverlayPanel.java"
+            line="548"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java"
+            line="102"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessorySheetCoordinator.java"
+            line="43"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_tabs/PasswordAccessorySheetCoordinator.java"
+            line="66"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java"
+            line="538"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/RequestGenerator.java"
+            line="43"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/rlz/RlzPingHandler.java"
+            line="40"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivity.java"
+            line="393"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java"
+            line="64"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java"
+            line="231"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
+            line="95"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
+            line="115"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within package private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SignInPromo.java"
+            line="122"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java"
+            line="802"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/support_library/java/src/org/chromium/support_lib_glue/SupportLibWebViewChromium.java"
+            line="50"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="88"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="182"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="190"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="197"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="212"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/SystemDownloadNotifier.java"
+            line="217"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java"
+            line="1564"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java"
+            line="641"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/omaha/UpdateStatusProvider.java"
+            line="423"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java"
+            line="974"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../android_webview/glue/java/src/com/android/webview/chromium/WebViewChromium.java"
+            line="1830"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLocator.java"
+            line="45"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
+            line="72"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
+            line="90"/>
+    </issue>
+
+    <issue
+        id="VisibleForTests"
+        message="This method should only be accessed from tests or within private scope">
+        <location
+            file="../../components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/WebsitePreferenceBridge.java"
+            line="145"/>
+    </issue>
+
+    <issue
+        id="Deprecated"
+        message="Job scheduling with `GcmNetworkManager` is deprecated: Use AndroidX `WorkManager` instead">
+        <location
+            file="../../components/background_task_scheduler/internal/android/java/src/org/chromium/components/background_task_scheduler/internal/BackgroundTaskSchedulerGcmNetworkManager.java"
+            line="249"/>
+    </issue>
+
+    <issue
+        id="UnspecifiedImmutableFlag"
+        message="Missing `PendingIntent` mutability flag">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/DownloadNotificationFactory.java"
+            line="274"/>
+    </issue>
+
+    <issue
+        id="UnspecifiedImmutableFlag"
+        message="Missing `PendingIntent` mutability flag">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationServiceImpl.java"
+            line="342"/>
+    </issue>
+
+    <issue
+        id="UnspecifiedImmutableFlag"
+        message="Missing `PendingIntent` mutability flag">
+        <location
+            file="../../chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java"
+            line="706"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/AppLanguagePromoDialog.java"
+            line="188"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
+            line="164"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
+            line="315"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
+            line="363"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
+            line="376"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java"
+            line="102"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java"
+            line="118"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/datareduction/settings/DataReductionPreferenceFragment.java"
+            line="143"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="551"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="574"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="611"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="646"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="660"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/DateDividedAdapter.java"
+            line="781"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java"
+            line="214"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/followmanagement/FollowManagementMediator.java"
+            line="154"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/history/HistoryAdapter.java"
+            line="132"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java"
+            line="209"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
+            line="133"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
+            line="201"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
+            line="212"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/content_creation/notes/internal/android/java/src/org/chromium/chrome/browser/content_creation/notes/NoteCreationDialog.java"
+            line="112"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/PickerAdapter.java"
+            line="169"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/PickerAdapter.java"
+            line="196"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/PickerAdapter.java"
+            line="213"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/PickerAdapter.java"
+            line="342"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/src/org/chromium/components/browser_ui/contacts_picker/PickerCategoryView.java"
+            line="220"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java"
+            line="259"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java"
+            line="395"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java"
+            line="455"/>
+    </issue>
+
+    <issue
+        id="NotifyDataSetChanged"
+        message="It will always be more efficient to use more specific change events if you can. Rely on `notifyDataSetChanged` as a last resort.">
+        <location
+            file="../../chrome/browser/webapps/android/java/src/org/chromium/chrome/browser/webapps/PwaBottomSheetController.java"
+            line="127"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_bitmap_view.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_bitmap_view.xml"
+            line="94"/>
+    </issue>
+
+    <issue
+        id="UseCompoundDrawables"
+        message="This tag and its children can be replaced by one `&lt;TextView/>` and a compound drawable">
+        <location
+            file="../../chrome/browser/share/android/java/res/layout/qrcode_camera_error_layout.xml"
+            line="11"/>
+    </issue>
+
+    <issue
+        id="MergeRootFrame"
+        message="This `&lt;FrameLayout>` can be replaced with a `&lt;merge>` tag">
+        <location
+            file="../../chrome/android/java/res/layout/signin_activity.xml"
+            line="5"/>
+    </issue>
+
+    <issue
+        id="UsableSpace"
+        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data">
+        <location
+            file="../../chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java"
+            line="156"/>
+    </issue>
+
+    <issue
+        id="UsableSpace"
+        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/download/OMADownloadHandler.java"
+            line="320"/>
+    </issue>
+
+    <issue
+        id="UsableSpace"
+        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java"
+            line="240"/>
+    </issue>
+
+    <issue
+        id="UsableSpace"
+        message="Consider also using `StorageManager#getAllocatableBytes` and `allocateBytes` which will consider clearable cached data">
+        <location
+            file="../../chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/storage/StorageSummaryProvider.java"
+            line="86"/>
+    </issue>
+
+    <issue
+        id="Autofill"
+        message="Missing `autofillHints` attribute">
+        <location
+            file="../../android_webview/nonembedded/java/res_devui/layout/fragment_flags.xml"
+            line="25"/>
+    </issue>
+
+    <issue
+        id="Autofill"
+        message="Missing `autofillHints` attribute">
+        <location
+            file="../../chrome/browser/password_check/android/java/res/layout/password_check_edit_fragment.xml"
+            line="31"/>
+    </issue>
+
+    <issue
+        id="Autofill"
+        message="Missing `autofillHints` attribute">
+        <location
+            file="../../chrome/browser/password_check/android/java/res/layout/password_check_edit_fragment.xml"
+            line="52"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `AccessibilityTabModelListItem` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/accessibility_tab_switcher/AccessibilityTabModelListItem.java"
+            line="458"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java"
+            line="236"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java"
+            line="299"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `BottomSheet` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java"
+            line="286"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``TextView`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataCheckBoxPreference.java"
+            line="54"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/browsing_data/ClearBrowsingDataCheckBoxPreference.java"
+            line="54"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `CompositorViewHolder` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/compositor/CompositorViewHolder.java"
+            line="654"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ContentView` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentView.java"
+            line="333"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageButton`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewTablet.java"
+            line="98"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``EditText`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
+            line="170"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
+            line="170"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``EditText`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../android_webview/nonembedded/java/src/org/chromium/android_webview/devui/FlagsFragment.java"
+            line="185"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `FullScreenView` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../android_webview/java/src/org/chromium/android_webview/FullScreenView.java"
+            line="91"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `InfoBarMessageView` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/infobars/android/java/src/org/chromium/components/infobars/InfoBarMessageView.java"
+            line="32"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageView`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
+            line="174"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java"
+            line="174"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``ImageButton`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/menu_button/MenuButton.java"
+            line="78"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
+            line="208"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
+            line="238"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view ``Button`` has `setOnTouchListener` called on it but does not override `performClick`">
+        <location
+            file="../../components/browser_ui/modaldialog/android/java/src/org/chromium/components/browser_ui/modaldialog/ModalDialogView.java"
+            line="240"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `NoSwipeViewPager` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../chrome/android/features/keyboard_accessory/internal/java/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/NoSwipeViewPager.java"
+            line="24"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerVideoPlayer.java"
+            line="242"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `PlayerFrameView` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameView.java"
+            line="136"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ScrimView` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/scrim/ScrimView.java"
+            line="79"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` lambda should call `View#performClick` when a click is detected">
+        <location
+            file="../../components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/selectable_list/SelectableListLayout.java"
+            line="236"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ToolbarControlContainer` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainer.java"
+            line="265"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `ToolbarPhone` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java"
+            line="503"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="Custom view `TouchRestrictingFrameLayout` overrides `onTouchEvent` but not `performClick`">
+        <location
+            file="../../components/browser_ui/bottomsheet/android/internal/java/src/org/chromium/components/browser_ui/bottomsheet/TouchRestrictingFrameLayout.java"
+            line="46"/>
+    </issue>
+
+    <issue
+        id="ClickableViewAccessibility"
+        message="`onTouch` should call `View#performClick` when a click is detected">
+        <location
+            file="../../weblayer/browser/java/org/chromium/weblayer_private/WebContentsGestureStateTracker.java"
+            line="48"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_bottom_sheet_content.xml"
+            line="8"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="49"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="49"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="73"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="73"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="97"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/contacts_picker/android/java/res/layout/contacts_list_item_view.xml"
+            line="97"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_dialog.xml"
+            line="41"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/photo_picker_dialog.xml"
+            line="41"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/android/java/res/layout/search_activity.xml"
+            line="28"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/android/java/res/layout/search_activity.xml"
+            line="28"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../chrome/browser/ui/android/toolbar/java/res/layout/start_top_toolbar.xml"
+            line="13"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="37"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="99"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="99"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="124"/>
+    </issue>
+
+    <issue
+        id="KeyboardInaccessibleWidget"
+        message="&apos;clickable&apos; attribute found, please also add &apos;focusable&apos;">
+        <location
+            file="../../components/browser_ui/photo_picker/android/java/res/layout/video_player.xml"
+            line="124"/>
     </issue>
 
 </issues>
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
index 7f2331d2..994748d 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -269,14 +269,8 @@
             mUrlFocusChangeListener = new UrlFocusChangeListener() {
                 @Override
                 public void onUrlFocusChange(boolean hasFocus) {
-                    if (hasFakeSearchBox()) {
-                        if (mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE)) {
-                            mSecondaryTasksSurfacePropertyModel.set(
-                                    IS_FAKE_SEARCH_BOX_VISIBLE, !hasFocus);
-                        } else {
-                            setFakeBoxVisibility(!hasFocus);
-                        }
-                    }
+                    assert !mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE);
+                    if (hasFakeSearchBox()) setFakeBoxVisibility(!hasFocus);
                     notifyStateChange();
                 }
             };
@@ -781,7 +775,7 @@
 
     /**
      * Set the visibility of secondary tasks surface. Secondary tasks surface is used for showing
-     * normal grid tab switcher, incognito gird tab switcher and incognito homepage.
+     * normal grid tab switcher and incognito gird tab switcher.
      * @param isVisible Whether secondary tasks surface is visible.
      * @param skipUpdateController Whether to skip mSecondaryTasksSurfaceController#showOverview and
      *         mSecondaryTasksSurfaceController#hideOverview.
@@ -795,8 +789,7 @@
                 mSecondaryTasksSurfaceController = mSecondaryTasksSurfaceInitializer.initialize();
             }
             if (mSecondaryTasksSurfacePropertyModel != null) {
-                mSecondaryTasksSurfacePropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE,
-                        mIsIncognito && mStartSurfaceState == StartSurfaceState.SHOWN_HOMEPAGE);
+                mSecondaryTasksSurfacePropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, false);
                 mSecondaryTasksSurfacePropertyModel.set(IS_INCOGNITO, mIsIncognito);
             }
             if (mSecondaryTasksSurfaceController != null && !skipUpdateController) {
@@ -829,14 +822,9 @@
     @VisibleForTesting
     public boolean shouldShowTabSwitcherToolbar() {
         // Always show in TABSWITCHER
-        if (mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER) return true;
-
-        if (mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE)) {
-            // Always show on the stack tab switcher secondary surface.
-            if (mSecondaryTasksSurfacePropertyModel == null) return true;
-
-            // Hide when focusing the Omnibox on the secondary surface.
-            return mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE);
+        if (mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER
+                || mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE)) {
+            return true;
         }
 
         // Hide when focusing the Omnibox on the primary surface.
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
index 4962ee878..dbcbee6f 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -1958,6 +1958,34 @@
         ReturnToChromeExperimentsUtil.setSyncForTesting(false);
     }
 
+    @Test
+    @MediumTest
+    @Feature({"StartSurface"})
+    @CommandLineFlags.Add({BASE_PARAMS + "/single"})
+    public void testNotShowIncognitoHomepage() {
+        if (!mImmediateReturn) {
+            StartSurfaceTestUtils.pressHomePageButton(mActivityTestRule.getActivity());
+        }
+
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        CriteriaHelper.pollUiThread(
+                () -> cta.getLayoutManager() != null && cta.getLayoutManager().overviewVisible());
+        StartSurfaceTestUtils.waitForTabModel(cta);
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> { cta.getTabModelSelector().getModel(false).closeAllTabs(); });
+        TabUiTestHelper.verifyTabModelTabCount(cta, 0, 0);
+        assertTrue(cta.getLayoutManager().overviewVisible());
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> cta.getTabCreator(true /*incognito*/).launchNTP());
+        TabUiTestHelper.verifyTabModelTabCount(cta, 0, 1);
+
+        // Simulates pressing the home button. Incognito tab should stay and homepage shouldn't
+        // show.
+        onView(withId(R.id.home_button)).perform(click());
+        assertFalse(cta.getLayoutManager().overviewVisible());
+        onViewWaiting(withId(R.id.new_tab_incognito_container)).check(matches(isDisplayed()));
+    }
+
     private void backActionDeleteBlankTabForOmniboxFocusedOnNewTabSingleSurface(
             Runnable backAction) {
         if (!mImmediateReturn) {
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
index 9a2c262b..63ddf5d 100644
--- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
+++ b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -558,22 +558,8 @@
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
 
         doReturn(2).when(mNormalTabModel).getCount();
-        mediator.setOverviewState(StartSurfaceState.SHOWING_HOMEPAGE);
-        mediator.showOverview(false);
-        assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_HOMEPAGE));
-        assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true));
-        assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true));
-        assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(MV_TILES_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_TAB_CAROUSEL_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE), equalTo(true));
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE),
-                equalTo(false));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
-
         mediator.setOverviewState(StartSurfaceState.SHOWN_TABSWITCHER);
+        mediator.showOverview(false);
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_TABSWITCHER));
         assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true));
         assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true));
@@ -585,20 +571,6 @@
                 equalTo(false));
         assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
 
-        mediator.setOverviewState(StartSurfaceState.SHOWN_HOMEPAGE);
-        assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_HOMEPAGE));
-        assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true));
-        assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true));
-        assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(MV_TILES_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_TAB_CAROUSEL_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE), equalTo(true));
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE),
-                equalTo(false));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
-
         mediator.hideOverview(false);
         mediator.startedHiding();
         assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.NOT_SHOWN));
@@ -633,19 +605,6 @@
         mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(
                 mIncognitoTabModel, mNormalTabModel);
 
-        assertThat(mediator.getStartSurfaceState(), equalTo(StartSurfaceState.SHOWN_HOMEPAGE));
-        assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true));
-        assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true));
-        assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(MV_TILES_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_TAB_CAROUSEL_VISIBLE), equalTo(false));
-        assertThat(mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE), equalTo(true));
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE),
-                equalTo(false));
-        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
-
         doReturn(false).when(mTabModelSelector).isIncognitoSelected();
         mTabModelSelector.selectModel(false);
         mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(
@@ -740,8 +699,8 @@
 
         mediator.setOverviewState(StartSurfaceState.SHOWN_HOMEPAGE);
         assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
+        assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE),
+                equalTo(false));
         assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE),
                 equalTo(false));
         assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_INCOGNITO), equalTo(true));
@@ -897,18 +856,8 @@
         doReturn(true).when(mTabModelSelector).isIncognitoSelected();
         mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(
                 mIncognitoTabModel, mNormalTabModel);
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
-        assertThat(mediator.shouldShowTabSwitcherToolbar(), equalTo(true));
-
-        mUrlFocusChangeListenerCaptor.getValue().onUrlFocusChange(true);
         assertThat(mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE),
                 equalTo(false));
-        assertThat(mediator.shouldShowTabSwitcherToolbar(), equalTo(false));
-
-        mUrlFocusChangeListenerCaptor.getValue().onUrlFocusChange(false);
-        assertThat(
-                mSecondaryTasksSurfacePropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE), equalTo(true));
         assertThat(mediator.shouldShowTabSwitcherToolbar(), equalTo(true));
     }
 
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 30141ab..b3f19080 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
@@ -32,13 +32,16 @@
 import com.google.android.material.color.MaterialColors;
 
 import org.chromium.base.CommandLine;
+import org.chromium.base.ObserverList;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
+import org.chromium.chrome.browser.feed.componentinterfaces.SurfaceCoordinator;
 import org.chromium.chrome.browser.feed.settings.FeedAutoplaySettingsFragment;
 import org.chromium.chrome.browser.feed.shared.FeedSurfaceDelegate;
 import org.chromium.chrome.browser.feed.shared.FeedSurfaceProvider;
 import org.chromium.chrome.browser.feed.shared.stream.Stream;
+import org.chromium.chrome.browser.feed.v2.FeedServiceBridgeDelegateImpl;
 import org.chromium.chrome.browser.feed.v2.FeedStream;
 import org.chromium.chrome.browser.feed.v2.NativeViewListRenderer;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -89,9 +92,9 @@
 /**
  * Provides a surface that displays an interest feed rendered list of content suggestions.
  */
-public class FeedSurfaceCoordinator implements FeedSurfaceProvider, FeedBubbleDelegate,
-                                               SwipeRefreshLayout.OnRefreshListener,
-                                               BackToTopBubbleScrollListener.ResultHandler {
+public class FeedSurfaceCoordinator
+        implements FeedSurfaceProvider, FeedBubbleDelegate, SwipeRefreshLayout.OnRefreshListener,
+                   BackToTopBubbleScrollListener.ResultHandler, SurfaceCoordinator {
     @VisibleForTesting
     public static final String FEED_STREAM_CREATED_TIME_MS_UMA = "FeedStreamCreatedTime";
 
@@ -112,6 +115,7 @@
     private final Supplier<ShareDelegate> mShareSupplier;
     private final Handler mHandler;
     private final boolean mOverScrollDisabled;
+    private final ObserverList<SurfaceCoordinator.Observer> mObservers = new ObserverList<>();
 
     private UiConfig mUiConfig;
     private FrameLayout mRootView;
@@ -292,7 +296,7 @@
             FeedLaunchReliabilityLoggingState launchReliabilityLoggingState,
             @Nullable FeedSwipeRefreshLayout swipeRefreshLayout, boolean overScrollDisabled,
             @Nullable ViewGroup viewportView) {
-        FeedSurfaceTracker.getInstance().initServiceBridge();
+        FeedSurfaceTracker.getInstance().initServiceBridge(new FeedServiceBridgeDelegateImpl());
         mActivity = activity;
         mSnackbarManager = snackbarManager;
         mNtpHeader = ntpHeader;
@@ -348,9 +352,10 @@
                 new FeedSurfaceMediator(this, mActivity, snapScrollHelper, mPageNavigationDelegate,
                         mSectionHeaderModel, getTabIdFromLaunchOrigin(launchOrigin));
 
+        FeedSurfaceTracker.getInstance().trackSurface(this);
+
         // Creates streams, initiates content changes.
         mMediator.updateContent();
-        FeedSurfaceTracker.getInstance().trackSurface(this);
 
         // Enable pull-to-refresh.
         if (mSwipeRefreshLayout != null) {
@@ -473,20 +478,25 @@
     }
 
     /** @return whether this coordinator is currently active. */
-    boolean isActive() {
+    @Override
+    public boolean isActive() {
         return mIsActive;
     }
 
     /** Shows the feed. */
+    @Override
     public void onSurfaceOpened() {
         // Guard on isStartupCalled.
         if (!FeedSurfaceTracker.getInstance().isStartupCalled()) return;
         mIsActive = true;
-
+        for (Observer observer : mObservers) {
+            observer.surfaceOpened();
+        }
         mMediator.onSurfaceOpened();
     }
 
     /** Hides the feed. */
+    @Override
     public void onSurfaceClosed() {
         if (!FeedSurfaceTracker.getInstance().isStartupCalled()) return;
         mIsActive = false;
@@ -1007,6 +1017,16 @@
         mBackToTopBubble = null;
     }
 
+    @Override
+    public void addObserver(SurfaceCoordinator.Observer observer) {
+        mObservers.addObserver(observer);
+    }
+
+    @Override
+    public void removeObserver(SurfaceCoordinator.Observer observer) {
+        mObservers.removeObserver(observer);
+    }
+
     private boolean isReliabilityLoggingEnabled() {
         return ChromeFeatureList.isEnabled(ChromeFeatureList.FEED_RELIABILITY_LOGGING)
                 && (mPrivacyPreferencesManager.isMetricsReportingEnabled()
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index b7f76b0..fd4632c 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -30,7 +30,6 @@
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceLifecycleManager.java",
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java",
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceScopeDependencyProvider.java",
-  "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java",
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSwipeRefreshLayout.java",
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HeaderIphScrollListener.java",
   "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/NtpFeedSurfaceLifecycleManager.java",
diff --git a/chrome/android/java/res/layout/power_bookmark_tag_chip_list.xml b/chrome/android/java/res/layout/power_bookmark_tag_chip_list.xml
new file mode 100644
index 0000000..39df0a9
--- /dev/null
+++ b/chrome/android/java/res/layout/power_bookmark_tag_chip_list.xml
@@ -0,0 +1,12 @@
+<?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.
+-->
+
+<view class="org.chromium.chrome.browser.bookmarks.PowerBookmarkTagChipList"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/power_bookmark_tag_chip_list"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index d5d2e9b3..cbe6a15 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -778,8 +778,11 @@
             OnClickListener bookmarkClickHandler = v -> addOrEditBookmark(getActivityTab());
 
             Supplier<Boolean> showStartSurfaceSupplier = () -> {
+                // If incognito is selected, tapping the home button stays on the current incognito
+                // tab.
                 if (ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePageOnPhone(
-                            this, isTablet())) {
+                            this, isTablet())
+                        && !mTabModelSelector.isIncognitoSelected()) {
                     StartSurfaceUserData.setKeepTab(getActivityTab(), true);
                     showOverview(StartSurfaceState.SHOWING_HOMEPAGE);
                     return true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
index 6be5944..d21ea1c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -141,6 +141,13 @@
     private void setBookmarks(List<BookmarkId> bookmarks) {
         clearHighlight();
         mElements.clear();
+
+        // Show the tag chiplist only for the shopping folder.
+        // TODO(crbug.com/1247825): Clarify how the tag list should interact with promo headers.
+        if (mCurrentFolder.getType() == ViewType.SHOPPING_POWER_BOOKMARK) {
+            mElements.add(BookmarkListEntry.createChipList());
+        }
+
         // Restore the header, if it exists, then update it.
         if (hasPromoHeader()) {
             mElements.add(BookmarkListEntry.createSyncPromoHeader(mPromoHeaderType));
@@ -187,6 +194,14 @@
         return holder;
     }
 
+    private ViewHolder createTagChipListViewHolder(ViewGroup parent) {
+        ViewGroup row = (ViewGroup) LayoutInflater.from(parent.getContext())
+                                .inflate(R.layout.power_bookmark_tag_chip_list, parent, false);
+        ViewHolder vh = new ViewHolder(row) {};
+        ((PowerBookmarkTagChipList) row).init(mDelegate.getModel());
+        return vh;
+    }
+
     @Override
     public ViewHolder onCreateViewHolder(ViewGroup parent, @ViewType int viewType) {
         assert mDelegate != null;
@@ -213,6 +228,8 @@
                 return new ViewHolder(
                         LayoutInflater.from(parent.getContext())
                                 .inflate(R.layout.horizontal_divider, parent, false)) {};
+            case ViewType.TAG_CHIP_LIST:
+                return createTagChipListViewHolder(parent);
             default:
                 assert false;
                 return null;
@@ -250,6 +267,9 @@
                 // We need this in case we are change state during a pulse.
                 ViewHighlighter.turnOffHighlight(holder.itemView);
             }
+        } else if (holder.getItemViewType() == ViewType.TAG_CHIP_LIST) {
+            PowerBookmarkTagChipList tagChipList = ((PowerBookmarkTagChipList) holder.itemView);
+            tagChipList.setBookmarkFolder(mCurrentFolder);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
index f473953c..89c2d58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkListEntry.java
@@ -26,7 +26,7 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({ViewType.INVALID, ViewType.PERSONALIZED_SIGNIN_PROMO, ViewType.PERSONALIZED_SYNC_PROMO,
             ViewType.SYNC_PROMO, ViewType.FOLDER, ViewType.BOOKMARK, ViewType.DIVIDER,
-            ViewType.SECTION_HEADER, ViewType.SHOPPING_POWER_BOOKMARK})
+            ViewType.SECTION_HEADER, ViewType.SHOPPING_POWER_BOOKMARK, ViewType.TAG_CHIP_LIST})
     @interface ViewType {
         int INVALID = -1;
         int PERSONALIZED_SIGNIN_PROMO = 0;
@@ -37,6 +37,7 @@
         int DIVIDER = 5;
         int SECTION_HEADER = 6;
         int SHOPPING_POWER_BOOKMARK = 7;
+        int TAG_CHIP_LIST = 8;
     }
 
     /**
@@ -154,4 +155,12 @@
     SectionHeaderData getSectionHeaderData() {
         return mSectionHeaderData;
     }
+
+    /**
+     * Creates a chip list.
+     */
+    static BookmarkListEntry createChipList() {
+        return new BookmarkListEntry(
+                ViewType.TAG_CHIP_LIST, /*bookmarkItem=*/null, /*sectionHeaderData=*/null);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java
new file mode 100644
index 0000000..9b12507
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipList.java
@@ -0,0 +1,180 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.bookmarks;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.chromium.base.ObserverList;
+import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
+import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver;
+import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta;
+import org.chromium.components.bookmarks.BookmarkId;
+import org.chromium.components.browser_ui.widget.chips.Chip;
+import org.chromium.components.browser_ui.widget.chips.ChipsCoordinator;
+import org.chromium.components.browser_ui.widget.chips.ChipsProvider;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/** Displays a chip list containing tags for the current folder. */
+public class PowerBookmarkTagChipList extends FrameLayout implements ChipsProvider {
+    private BookmarkId mCurrentFolder;
+    private BookmarkModel mBookmarkModel;
+    private ChipsCoordinator mChipsCoordinator;
+
+    private final ObserverList<ChipsProvider.Observer> mChipsProviderObservers =
+            new ObserverList<>();
+    private final List<Chip> mChips = new ArrayList<>();
+    private final Map<String, Integer> mTagMap = new HashMap<>();
+
+    private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() {
+        @Override
+        public void bookmarkModelChanged() {
+            populateChipsForCurrentFolder();
+        }
+    };
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    public PowerBookmarkTagChipList(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void onFinishInflate() {
+        super.onFinishInflate();
+
+        mChipsCoordinator = new ChipsCoordinator(getContext(), /* chipsProvider= */ this);
+        addView(mChipsCoordinator.getView());
+    }
+
+    /**
+     * Initializes the object with the given {@link BookmarkModel} which allows observation of
+     * changes the the underlying data.
+     * @param bookmarkModel The {@link BookmarkModel} which manages bookmark data.
+     */
+    public void init(BookmarkModel bookmarkModel) {
+        mBookmarkModel = bookmarkModel;
+        mBookmarkModel.addObserver(mBookmarkModelObserver);
+    }
+
+    /**
+     * Sets the current folder which contains the bookmarks to populate the tag chip list. The
+     * tag chip list is currently populated under the assumption that all the relevant bookmarks
+     * will be direct children of the given folder.
+     * @param currentFolder The current folder to retrieve child bookmarks from.
+     */
+    public void setBookmarkFolder(BookmarkId currentFolder) {
+        mCurrentFolder = currentFolder;
+        populateChipsForCurrentFolder();
+    }
+
+    private void populateChipsForCurrentFolder() {
+        mTagMap.clear();
+        mChips.clear();
+        for (BookmarkId id : mBookmarkModel.getChildIDs(mCurrentFolder)) {
+            BookmarkItem item = mBookmarkModel.getBookmarkById(id);
+            // TODO(crbug.com/1247825): Call #populateChipsForPowerBookmarkMeta will bookmark
+            // metadata once available.
+        }
+        notifyObservers();
+    }
+
+    @VisibleForTesting
+    void populateTagMapForPowerBookmarkMeta(PowerBookmarkMeta powerBookmarkMeta) {
+        for (int i = 0; i < powerBookmarkMeta.getTagsCount(); i++) {
+            String tag = powerBookmarkMeta.getTags(i).getDisplayName();
+            if (!mTagMap.containsKey(tag)) mTagMap.put(tag, 0);
+
+            mTagMap.put(tag, mTagMap.get(tag) + 1);
+        }
+    }
+
+    @VisibleForTesting
+    void populateChipListFromCurrentTagMap() {
+        List<Map.Entry<String, Integer>> entryList = new ArrayList<>(mTagMap.entrySet());
+        Collections.sort(entryList, new Comparator<Map.Entry<String, Integer>>() {
+            @Override
+            public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
+                return o2.getValue().compareTo(o1.getValue());
+            }
+        });
+
+        for (int i = 0; i < entryList.size(); i++) {
+            Map.Entry<String, Integer> entry = entryList.get(i);
+            String tag = entry.getKey();
+
+            Chip chip =
+                    new Chip(i, tag, Chip.INVALID_ICON_ID, () -> { toggleSelectionForTag(tag); });
+            chip.enabled = true;
+            mChips.add(chip);
+        }
+    }
+
+    private void toggleSelectionForTag(String tag) {
+        Chip chip = getChipForTag(tag);
+        if (chip == null) {
+            assert false : "Attempt to select a tag that's not present, tag=" + tag;
+            return;
+        }
+
+        chip.selected = !chip.selected;
+        notifyObservers();
+    }
+
+    private Chip getChipForTag(String tag) {
+        for (int i = 0; i < mChips.size(); i++) {
+            Chip chip = mChips.get(i);
+            if (TextUtils.equals(chip.rawText, tag)) return chip;
+        }
+        return null;
+    }
+
+    @VisibleForTesting
+    void notifyObservers() {
+        for (Observer observer : mChipsProviderObservers) {
+            observer.onChipsChanged();
+        }
+    }
+
+    // ChipsProvider implementation
+
+    @Override
+    public void addObserver(Observer observer) {
+        mChipsProviderObservers.addObserver(observer);
+    }
+
+    @Override
+    public void removeObserver(Observer observer) {
+        mChipsProviderObservers.removeObserver(observer);
+    }
+
+    @Override
+    public List<Chip> getChips() {
+        return mChips;
+    }
+
+    @Override
+    public int getChipSpacingPx() {
+        return getContext().getResources().getDimensionPixelSize(
+                org.chromium.chrome.R.dimen.contextual_search_chip_list_chip_spacing);
+    }
+
+    @Override
+    public int getSidePaddingPx() {
+        return getContext().getResources().getDimensionPixelSize(
+                org.chromium.chrome.R.dimen.contextual_search_chip_list_side_padding);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DefaultSearchEngineFirstRunFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DefaultSearchEngineFirstRunFragment.java
index ee521758..fbb108c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DefaultSearchEngineFirstRunFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/DefaultSearchEngineFirstRunFragment.java
@@ -102,4 +102,4 @@
 
         mShownRecorded = true;
     }
-}
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
index 10ec995..ab50be3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -59,8 +59,7 @@
      */
     public interface FirstRunActivityObserver {
         /** See {@link #onCreatePostNativeAndPoliciesPageSequence}. */
-        void onCreatePostNativeAndPoliciesPageSequence(
-                FirstRunActivity caller, Bundle freProperties);
+        void onCreatePostNativeAndPoliciesPageSequence(FirstRunActivity caller);
 
         /** See {@link #acceptTermsOfService}. */
         void onAcceptTermsOfService(FirstRunActivity caller);
@@ -216,8 +215,7 @@
         mPostNativeAndPolicyPagesCreated = true;
 
         if (sObserver != null) {
-            sObserver.onCreatePostNativeAndPoliciesPageSequence(
-                    FirstRunActivity.this, mFreProperties);
+            sObserver.onCreatePostNativeAndPoliciesPageSequence(FirstRunActivity.this);
         }
     }
 
@@ -435,7 +433,7 @@
         if (mPager.getCurrentItem() == 0) {
             abortFirstRunExperience();
         } else {
-            setCurrentItemForPager(mPager.getCurrentItem() - 1);
+            jumpToPage(mPager.getCurrentItem() - 1);
         }
     }
 
@@ -446,8 +444,12 @@
     }
 
     @Override
-    public void advanceToNextPage() {
-        jumpToPage(mPager.getCurrentItem() + 1);
+    public boolean advanceToNextPage() {
+        int position = mPager.getCurrentItem() + 1;
+        if (!jumpToPage(position)) return false;
+
+        recordFreProgressHistogram(mFreProgressStates.get(position));
+        return true;
     }
 
     @Override
@@ -549,7 +551,7 @@
 
         if (sObserver != null) sObserver.onAcceptTermsOfService(this);
 
-        jumpToPage(mPager.getCurrentItem() + 1);
+        advanceToNextPage();
     }
 
     /** Initialize local state from launch intent and from saved instance state. */
@@ -570,16 +572,14 @@
      * @return Whether the transition to a given page was allowed.
      */
     private boolean jumpToPage(int position) {
+        // TODO(http://crbug.com/1250285): Simplify this condition if checking for ToS acceptance is
+        // not needed at this point.
+        boolean jumpToPageSuccess =
+                didAcceptTermsOfService() ? setCurrentItemForPager(position) : position == 0;
+
         if (sObserver != null) sObserver.onJumpToPage(this, position);
 
-        if (!didAcceptTermsOfService()) {
-            return position == 0;
-        }
-        if (!setCurrentItemForPager(position)) {
-            return false;
-        }
-        recordFreProgressHistogram(mFreProgressStates.get(position));
-        return true;
+        return jumpToPageSuccess;
     }
 
     private boolean setCurrentItemForPager(int position) {
@@ -605,13 +605,12 @@
     }
 
     private void skipPagesIfNecessary() {
-        boolean shouldSkip = mPages.get(mPager.getCurrentItem()).shouldSkipPageOnCreate();
-        while (shouldSkip) {
-            if (!jumpToPage(mPager.getCurrentItem() + 1)) return;
-            shouldSkip = mPages.get(mPager.getCurrentItem()).shouldSkipPageOnCreate();
+        while (mPages.get(mPager.getCurrentItem()).shouldSkipPageOnCreate()
+                && advanceToNextPage()) {
         }
     }
 
+    // TODO(http://crbug.com/1250289): Ensure each state is only recorded once.
     private void recordFreProgressHistogram(int state) {
         if (mLaunchedFromChromeIcon) {
             RecordHistogram.recordEnumeratedHistogram(
@@ -634,6 +633,11 @@
     }
 
     @VisibleForTesting
+    public FirstRunFragment getCurrentFragmentForTesting() {
+        return mPagerAdapter.getFirstRunFragment(mPager.getCurrentItem());
+    }
+
+    @VisibleForTesting
     public static void setObserverForTest(FirstRunActivityObserver observer) {
         assert sObserver == null;
         sObserver = observer;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
index 192998ef..f946542 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunFlowSequencer.java
@@ -128,6 +128,15 @@
     }
 
     @VisibleForTesting
+    protected boolean shoulShowSignInPage() {
+        // We show the sign-in page if sync is allowed, and not signed in, and
+        // - "skip the first use hints" is not set, or
+        // - "skip the first use hints" is set, but there is at least one account.
+        return isSyncAllowed() && !isSignedIn()
+                && (!shouldSkipFirstUseHints() || !mGoogleAccounts.isEmpty());
+    }
+
+    @VisibleForTesting
     protected void setFirstRunFlowSignInComplete() {
         FirstRunSignInProcessor.setFirstRunFlowSignInComplete(true);
     }
@@ -155,12 +164,7 @@
      * @param freProperties Resulting FRE properties bundle.
      */
     public void onNativeAndPoliciesInitialized(Bundle freProperties) {
-        // We show the sign-in page if sync is allowed, and not signed in, and
-        // - no "skip the first use hints" is set, or
-        // - "skip the first use hints" is set, but there is at least one account.
-        boolean offerSignInOk = isSyncAllowed() && !isSignedIn()
-                && (!shouldSkipFirstUseHints() || !mGoogleAccounts.isEmpty());
-        freProperties.putBoolean(FirstRunActivity.SHOW_SIGNIN_PAGE, offerSignInOk);
+        freProperties.putBoolean(FirstRunActivity.SHOW_SIGNIN_PAGE, shoulShowSignInPage());
         freProperties.putBoolean(
                 FirstRunActivity.SHOW_DATA_REDUCTION_PAGE, shouldShowDataReductionPage());
         freProperties.putBoolean(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
index 7fd4982c..36d1a64 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunPageDelegate.java
@@ -20,8 +20,9 @@
     /**
      * Advances the First Run Experience to the next page.
      * Successfully finishes FRE if the current page is the last page.
+     * @return Whether advancing to the next page succeeded.
      */
-    void advanceToNextPage();
+    boolean advanceToNextPage();
 
     /**
      * Unsuccessfully aborts the First Run Experience.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentIntegrationTest.java
index 6b8daf6..d0eaea85 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/attribution_reporting/AttributionIntentIntegrationTest.java
@@ -65,7 +65,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class AttributionIntentIntegrationTest {
     @Rule
     public ChromeTabbedActivityTestRule mTabbedActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
index 4782979f..098541e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
@@ -43,7 +43,6 @@
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class PersonalDataManagerTest {
     private static final Bitmap TEST_CARD_ART_IMAGE =
             Bitmap.createBitmap(100, 200, Bitmap.Config.ARGB_8888);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
index 0d0d787..2819b2c9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill/settings/AutofillPaymentMethodsFragmentTest.java
@@ -34,7 +34,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class AutofillPaymentMethodsFragmentTest {
     @Rule
     public TestRule mFeaturesProcessorRule = new Features.JUnitProcessor();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
index 0c254c9..74cb70d2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -40,7 +40,6 @@
  */
 @RunWith(BaseJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class BookmarkBridgeTest {
     @Rule
     public final ChromeBrowserTestRule mChromeBrowserTestRule = new ChromeBrowserTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java
new file mode 100644
index 0000000..2b423ab
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/PowerBookmarkTagChipListTest.java
@@ -0,0 +1,179 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.bookmarks;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static org.hamcrest.CoreMatchers.allOf;
+import static org.hamcrest.Matchers.containsString;
+
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
+import androidx.test.filters.MediumTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.power_bookmarks.PowerBookmarkMeta;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.DummyUiChromeActivityTestCase;
+import org.chromium.chrome.test.util.ChromeRenderTestRule;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import java.io.IOException;
+
+/**
+ * Tests for the power bookmark experience.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+public class PowerBookmarkTagChipListTest extends DummyUiChromeActivityTestCase {
+    @Rule
+    public ChromeRenderTestRule mRenderTestRule =
+            ChromeRenderTestRule.Builder.withPublicCorpus().build();
+
+    private ViewGroup mContentView;
+    private PowerBookmarkTagChipList mTagChipList;
+
+    @Override
+    public void setUpTest() throws Exception {
+        super.setUpTest();
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mContentView = new LinearLayout(getActivity());
+
+            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                    ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
+
+            getActivity().setContentView(mContentView, params);
+            mTagChipList =
+                    (PowerBookmarkTagChipList) getActivity()
+                            .getLayoutInflater()
+                            .inflate(R.layout.power_bookmark_tag_chip_list, mContentView, true)
+                            .findViewById(R.id.power_bookmark_tag_chip_list);
+            mTagChipList.setVisibility(View.VISIBLE);
+        });
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    public void testTagList() throws IOException {
+        PowerBookmarkMeta.Builder meta = PowerBookmarkMeta.newBuilder();
+        PowerBookmarkMeta.Tag.Builder tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("foo");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("bar");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("baz");
+        meta.addTags(tag);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTagChipList.populateTagMapForPowerBookmarkMeta(meta.build());
+            mTagChipList.populateChipListFromCurrentTagMap();
+            mTagChipList.notifyObservers();
+        });
+
+        onView(withText(allOf(containsString("foo")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("bar")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("baz")))).check(matches(isDisplayed()));
+        mRenderTestRule.render(mContentView, "tag_list");
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    public void testTagListLarge() throws IOException {
+        PowerBookmarkMeta.Builder meta = PowerBookmarkMeta.newBuilder();
+        PowerBookmarkMeta.Tag.Builder tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("heeeeeeelllllllooooooo");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("wooooooooooorld");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("this");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("test");
+        meta.addTags(tag);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTagChipList.populateTagMapForPowerBookmarkMeta(meta.build());
+            mTagChipList.populateChipListFromCurrentTagMap();
+            mTagChipList.notifyObservers();
+        });
+
+        onView(withText(allOf(containsString("heeeeeeelllllllooooooo"))))
+                .check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("wooooooooooorld")))).check(matches(isDisplayed()));
+        mRenderTestRule.render(mContentView, "tag_list_large");
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    public void testTagListTagSelected() throws IOException {
+        PowerBookmarkMeta.Builder meta = PowerBookmarkMeta.newBuilder();
+        PowerBookmarkMeta.Tag.Builder tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("foo");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("bar");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("baz");
+        meta.addTags(tag);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTagChipList.populateTagMapForPowerBookmarkMeta(meta.build());
+            mTagChipList.populateChipListFromCurrentTagMap();
+            mTagChipList.notifyObservers();
+        });
+
+        onView(withText(allOf(containsString("foo")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("foo")))).perform(click());
+        onView(withText(allOf(containsString("bar")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("baz")))).check(matches(isDisplayed()));
+        mRenderTestRule.render(mContentView, "tag_list_tag_selected");
+    }
+
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    public void testTagListDuplicate() throws IOException {
+        PowerBookmarkMeta.Builder meta = PowerBookmarkMeta.newBuilder();
+        PowerBookmarkMeta.Tag.Builder tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("foo");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("bar");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("foo");
+        meta.addTags(tag);
+        tag = PowerBookmarkMeta.Tag.newBuilder();
+        tag.setDisplayName("baz");
+        meta.addTags(tag);
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mTagChipList.populateTagMapForPowerBookmarkMeta(meta.build());
+            mTagChipList.populateChipListFromCurrentTagMap();
+            mTagChipList.notifyObservers();
+        });
+
+        onView(withText(allOf(containsString("foo")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("bar")))).check(matches(isDisplayed()));
+        onView(withText(allOf(containsString("baz")))).check(matches(isDisplayed()));
+        mRenderTestRule.render(mContentView, "tag_list_duplicate");
+    }
+}
\ No newline at end of file
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 8ed0b3f..4547c868 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
@@ -21,7 +21,6 @@
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.Batch.SplitByFeature;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -47,7 +46,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Batch(Batch.PER_CLASS)
-@SplitByFeature
 public class ContextualSearchPolicyTest {
     @ClassRule
     public static ChromeTabbedActivityTestRule sActivityTestRule =
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadInfoBarControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadInfoBarControllerTest.java
index 7caa0ea..04fa3960 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadInfoBarControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadInfoBarControllerTest.java
@@ -37,7 +37,6 @@
 @Features.EnableFeatures(ChromeFeatureList.DOWNLOAD_PROGRESS_INFOBAR)
 @Features.DisableFeatures(ChromeFeatureList.DOWNLOAD_PROGRESS_MESSAGE)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class DownloadInfoBarControllerTest {
     @Rule
     public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java
index f4c9d2e1..0ea6ce1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerTest.java
@@ -39,7 +39,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Features.EnableFeatures(ChromeFeatureList.DOWNLOAD_PROGRESS_MESSAGE)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class DownloadMessageUiControllerTest {
     @Rule
     public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
index 5b90b4ab..e674fff 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImplTest.java
@@ -40,7 +40,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Features.DisableFeatures(
         {ChromeFeatureList.AUTOFILL_ASSISTANT, ChromeFeatureList.AUTOFILL_ASSISTANT_CHROME_ENTRY})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivityTestObserver.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivityTestObserver.java
index 55e07f0f..f1cf3a8f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivityTestObserver.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunActivityTestObserver.java
@@ -4,8 +4,6 @@
 
 package org.chromium.chrome.browser.firstrun;
 
-import android.os.Bundle;
-
 import org.chromium.base.test.util.CallbackHelper;
 
 import java.util.HashMap;
@@ -22,7 +20,6 @@
         public final CallbackHelper updateCachedEngineCallback = new CallbackHelper();
         public final CallbackHelper abortFirstRunExperienceCallback = new CallbackHelper();
         public final CallbackHelper exitFirstRunCallback = new CallbackHelper();
-        public Bundle freProperties;
     }
 
     private final Map<FirstRunActivity, ScopedObserverData> mScopeObserverDataMap = new HashMap<>();
@@ -35,10 +32,8 @@
     }
 
     @Override
-    public void onCreatePostNativeAndPoliciesPageSequence(
-            FirstRunActivity caller, Bundle freProperties) {
+    public void onCreatePostNativeAndPoliciesPageSequence(FirstRunActivity caller) {
         ScopedObserverData scopedObserverData = getScopedObserverData(caller);
-        scopedObserverData.freProperties = freProperties;
         scopedObserverData.createPostNativeAndPoliciesPageSequenceCallback.notifyCalled();
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
index 2efe8cc..84d97435 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/FirstRunIntegrationTest.java
@@ -6,6 +6,8 @@
 
 import static org.hamcrest.Matchers.is;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.when;
 
 import android.accounts.Account;
 import android.app.Activity;
@@ -23,6 +25,7 @@
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 
+import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 import org.junit.After;
 import org.junit.Assert;
@@ -45,6 +48,7 @@
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.JniMocker;
 import org.chromium.base.test.util.ScalableTimeout;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
@@ -57,12 +61,17 @@
 import org.chromium.chrome.browser.firstrun.FirstRunActivityTestObserver.ScopedObserverData;
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.locale.LocaleManagerDelegate;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
+import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettingsJni;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl;
 import org.chromium.chrome.browser.search_engines.DefaultSearchEngineDialogHelperUtils;
 import org.chromium.chrome.browser.search_engines.SearchEnginePromoType;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
+import org.chromium.chrome.browser.signin.SigninFirstRunFragment;
+import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
+import org.chromium.chrome.browser.signin.services.SigninManager;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.MultiActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
@@ -70,6 +79,7 @@
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
+import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.content_public.common.ContentUrlConstants;
@@ -98,12 +108,23 @@
     @Rule
     public TestRule mProcessor = new Features.JUnitProcessor();
 
+    @Rule
+    public JniMocker mJniMocker = new JniMocker();
+
     @Mock
     public FirstRunAppRestrictionInfo mMockAppRestrictionInfo;
     @Mock
     public EnterpriseInfo mEnterpriseInfo;
     @Mock
     private AccountManagerFacade mAccountManagerFacade;
+    @Mock
+    private DataReductionProxySettings.Natives mDataReductionJniMock;
+    @Mock
+    private SigninManager mSigninManagerMock;
+    @Mock
+    private IdentityManager mIdentityManagerMock;
+    @Mock
+    private IdentityServicesProvider mIdentityServiceProviderMock;
 
     private Promise<List<Account>> mAccountsPromise;
 
@@ -149,6 +170,7 @@
         ToSAndUMAFirstRunFragment.setShowUmaCheckBoxForTesting(false);
         EnterpriseInfo.setInstanceForTest(null);
         AccountManagerFacadeProvider.resetInstanceForTests();
+        IdentityServicesProvider.setInstanceForTests(null);
     }
 
     private ActivityMonitor getMonitor(Class activityClass) {
@@ -224,51 +246,30 @@
         mContext.startActivity(intent);
     }
 
-    private void clickThroughFirstRun(FirstRunActivity firstRunActivity,
-            @SearchEnginePromoType final int searchPromoType) throws Exception {
-        ScopedObserverData scopedObserverData = getObserverData(firstRunActivity);
-        scopedObserverData.createPostNativeAndPoliciesPageSequenceCallback.waitForCallback(
-                "Failed to finalize the flow and create subsequent pages", 0);
-        Bundle freProperties = scopedObserverData.freProperties;
-        Assert.assertEquals("Search engine name should not have been set yet", 0,
-                scopedObserverData.updateCachedEngineCallback.getCallCount());
+    private void clickThroughFirstRun(
+            FirstRunActivity firstRunActivity, FirstRunPagesTestCase testCase) throws Exception {
+        initializePreferences(testCase);
 
-        // Accept the ToS.
-        clickButton(firstRunActivity, R.id.terms_accept, "Failed to accept ToS");
-        scopedObserverData.jumpToPageCallback.waitForCallback(
-                "Failed to try moving to the next screen", 0);
-        scopedObserverData.acceptTermsOfServiceCallback.waitForCallback(
-                "Failed to accept the ToS", 0);
+        // Start FRE.
+        FirstRunNavigationHelper navigationHelper = new FirstRunNavigationHelper(firstRunActivity);
+        navigationHelper.ensurePagesCreationSucceeded().acceptTermsOfService();
 
-        // Acknowledge that Data Saver will be enabled.
-        if (freProperties.getBoolean(FirstRunActivityBase.SHOW_DATA_REDUCTION_PAGE)) {
-            int jumpCallCount = scopedObserverData.jumpToPageCallback.getCallCount();
-            clickButton(firstRunActivity, R.id.next_button, "Failed to skip data saver");
-            scopedObserverData.jumpToPageCallback.waitForCallback(
-                    "Failed try to move past the data saver fragment", jumpCallCount);
-        }
-
-        // Select a default search engine.
-        if (searchPromoType == SearchEnginePromoType.DONT_SHOW) {
-            Assert.assertFalse("Search engine page was shown.",
-                    freProperties.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE));
+        if (testCase.showDataSaverPromo()) {
+            navigationHelper.acknowledgeDataSaverEnabled();
         } else {
-            Assert.assertTrue("Search engine page wasn't shown.",
-                    freProperties.getBoolean(FirstRunActivityBase.SHOW_SEARCH_ENGINE_PAGE));
-            int jumpCallCount = scopedObserverData.jumpToPageCallback.getCallCount();
-            DefaultSearchEngineDialogHelperUtils.clickOnFirstEngine(
-                    firstRunActivity.findViewById(android.R.id.content));
-
-            scopedObserverData.jumpToPageCallback.waitForCallback(
-                    "Failed trying to move past the search engine fragment", jumpCallCount);
+            navigationHelper.ensureDataSaverPromoNotCurrentPage();
         }
 
-        // Don't sign in the user.
-        if (freProperties.getBoolean(FirstRunActivityBase.SHOW_SIGNIN_PAGE)) {
-            int jumpCallCount = scopedObserverData.jumpToPageCallback.getCallCount();
-            clickButton(firstRunActivity, R.id.negative_button, "Failed to skip signing-in");
-            scopedObserverData.jumpToPageCallback.waitForCallback(
-                    "Failed trying to move past the sign in fragment", jumpCallCount);
+        if (testCase.searchPromoType() == SearchEnginePromoType.DONT_SHOW) {
+            navigationHelper.ensureDefaultSearchEnginePromoNotCurrentPage();
+        } else {
+            navigationHelper.selectDefaultSearchEngine();
+        }
+
+        if (testCase.showSigninPromo()) {
+            navigationHelper.skipSigninPromo();
+        } else {
+            navigationHelper.ensureSigninPromoNotCurrentPage();
         }
     }
 
@@ -376,44 +377,186 @@
 
     @Test
     @MediumTest
-    public void testDefaultSearchEngine_DontShow() throws Exception {
-        runSearchEnginePromptTest(SearchEnginePromoType.DONT_SHOW);
+    public void testFirstRunPages_NoCctPolicy_AbsenceOfPromos() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase());
     }
 
     @Test
     @MediumTest
-    public void testDefaultSearchEngine_ShowExisting() throws Exception {
-        runSearchEnginePromptTest(SearchEnginePromoType.SHOW_EXISTING);
+    public void testFirstRunPages_NoCctPolicy_DataSaverPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withDataSaverPromo());
     }
 
     @Test
     @MediumTest
-    public void testDefaultSearchEngine_WithCctPolicy() throws Exception {
-        skipTosDialogViaPolicy();
-
-        runSearchEnginePromptTest(SearchEnginePromoType.SHOW_EXISTING);
+    public void testFirstRunPages_NoCctPolicy_DataSaverPromo_SearchPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withDataSaverPromo().withSearchPromo());
     }
 
-    private void runSearchEnginePromptTest(@SearchEnginePromoType final int searchPromoType)
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_DataSaverPromo_SearchPromo_SigninPromo()
             throws Exception {
-        // Force the LocaleManager into a specific state.
-        LocaleManagerDelegate mockDelegate = new LocaleManagerDelegate() {
-            @Override
-            public int getSearchEnginePromoShowType() {
-                return searchPromoType;
-            }
+        runFirstRunPagesTest(new FirstRunPagesTestCase()
+                                     .withDataSaverPromo()
+                                     .withSearchPromo()
+                                     .withSigninPromo());
+    }
 
-            @Override
-            public List<TemplateUrl> getSearchEnginesForPromoDialog(int promoType) {
-                return TemplateUrlServiceFactory.get().getTemplateUrls();
-            }
-        };
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> LocaleManager.getInstance().setDelegateForTest(mockDelegate));
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_DataSaverPromo_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withDataSaverPromo().withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_SearchPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withSearchPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_SearchPromo_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withSearchPromo().withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_NoCctPolicy_OnBackPressed() throws Exception {
+        initializePreferences(new FirstRunPagesTestCase()
+                                      .withDataSaverPromo()
+                                      .withSearchPromo()
+                                      .withSigninPromo());
 
         FirstRunActivity firstRunActivity = launchFirstRunActivity();
 
-        clickThroughFirstRun(firstRunActivity, searchPromoType);
+        // Go until the last page without skipping the last one, go back until initial page, and
+        // then complete first run.
+        new FirstRunNavigationHelper(firstRunActivity)
+                .ensurePagesCreationSucceeded()
+                .acceptTermsOfService()
+                .acknowledgeDataSaverEnabled()
+                .selectDefaultSearchEngine()
+                .ensureSigninPromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureDefaultSearchEnginePromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureDataSaverPromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureTermsOfServiceIsCurrentPage()
+                .acceptTermsOfService()
+                .acknowledgeDataSaverEnabled()
+                .selectDefaultSearchEngine()
+                .skipSigninPromo();
+
+        waitForActivity(ChromeTabbedActivity.class);
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_AbsenceOfPromos() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withCctTosDisabled());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_DataSaverPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withCctTosDisabled().withDataSaverPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_DataSaverPromo_SearchPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase()
+                                     .withCctTosDisabled()
+                                     .withDataSaverPromo()
+                                     .withSearchPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_DataSaverPromo_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase()
+                                     .withCctTosDisabled()
+                                     .withDataSaverPromo()
+                                     .withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_DataSaverPromo_SearchPromo_SigninPromo()
+            throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase()
+                                     .withCctTosDisabled()
+                                     .withDataSaverPromo()
+                                     .withSearchPromo()
+                                     .withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_SearchPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withCctTosDisabled().withSearchPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_SearchPromo_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase()
+                                     .withCctTosDisabled()
+                                     .withSearchPromo()
+                                     .withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_SigninPromo() throws Exception {
+        runFirstRunPagesTest(new FirstRunPagesTestCase().withCctTosDisabled().withSigninPromo());
+    }
+
+    @Test
+    @MediumTest
+    public void testFirstRunPages_WithCctPolicy_OnBackPressed() throws Exception {
+        initializePreferences(new FirstRunPagesTestCase()
+                                      .withCctTosDisabled()
+                                      .withDataSaverPromo()
+                                      .withSearchPromo()
+                                      .withSigninPromo());
+
+        FirstRunActivity firstRunActivity = launchFirstRunActivity();
+
+        // Go until the last page without skipping the last one, go back until initial page, and
+        // then complete first run.
+        new FirstRunNavigationHelper(firstRunActivity)
+                .ensurePagesCreationSucceeded()
+                .acceptTermsOfService()
+                .acknowledgeDataSaverEnabled()
+                .selectDefaultSearchEngine()
+                .ensureSigninPromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureDefaultSearchEnginePromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureDataSaverPromoIsCurrentPage()
+                .goBackToPreviousPage()
+                .ensureTermsOfServiceIsCurrentPage()
+                .acceptTermsOfService()
+                .acknowledgeDataSaverEnabled()
+                .selectDefaultSearchEngine()
+                .skipSigninPromo();
+
+        waitForActivity(ChromeTabbedActivity.class);
+    }
+
+    private void runFirstRunPagesTest(FirstRunPagesTestCase testCase) throws Exception {
+        FirstRunActivity firstRunActivity = launchFirstRunActivity();
+        clickThroughFirstRun(firstRunActivity, testCase);
 
         // FRE should be completed now, which will kick the user back into the interrupted flow.
         // In this case, the user gets sent to the ChromeTabbedActivity after a View Intent is
@@ -424,11 +567,36 @@
         waitForActivity(ChromeTabbedActivity.class);
     }
 
+    private void initializePreferences(FirstRunPagesTestCase testCase) throws Exception {
+        if (testCase.cctTosDisabled()) skipTosDialogViaPolicy();
+
+        if (testCase.showDataSaverPromo()) {
+            when(mDataReductionJniMock.isDataReductionProxyManaged(anyLong(), any()))
+                    .thenReturn(false);
+            when(mDataReductionJniMock.isDataReductionProxyFREPromoAllowed(anyLong(), any()))
+                    .thenReturn(true);
+        } else {
+            when(mDataReductionJniMock.isDataReductionProxyManaged(anyLong(), any()))
+                    .thenReturn(true);
+        }
+
+        setUpLocaleManagerDelegate(testCase.searchPromoType());
+
+        mJniMocker.mock(DataReductionProxySettingsJni.TEST_HOOKS, mDataReductionJniMock);
+        when(mIdentityServiceProviderMock.getIdentityManager(any()))
+                .thenReturn(mIdentityManagerMock);
+        when(mIdentityServiceProviderMock.getSigninManager(any())).thenReturn(mSigninManagerMock);
+        IdentityServicesProvider.setInstanceForTests(mIdentityServiceProviderMock);
+
+        when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(!testCase.showSigninPromo());
+        when(mSigninManagerMock.isSigninSupported()).thenReturn(testCase.showSigninPromo());
+    }
+
     @Test
     @MediumTest
     @DisabledTest(message = "https://crbug.com/1221647")
-    public void testExitFirstRunWithPolicy() {
-        skipTosDialogViaPolicy();
+    public void testExitFirstRunWithPolicy() throws Exception {
+        initializePreferences(new FirstRunPagesTestCase().withCctTosDisabled());
 
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(mContext, TEST_URL);
         mContext.startActivity(intent);
@@ -450,12 +618,15 @@
 
     @Test
     @MediumTest
-    public void testFirstRunSkippedSharedPreferenceRefresh() {
+    public void testFirstRunSkippedSharedPreferenceRefresh() throws Exception {
         // Set that the first run was previous skipped by policy in shared preference, then
         // refreshing shared preference should cause its value to become false, since there's no
         // policy set in this test case.
         FirstRunStatus.setFirstRunSkippedByPolicy(true);
 
+        when(mSigninManagerMock.isSigninDisabledByPolicy()).thenReturn(false);
+        when(mSigninManagerMock.isSigninSupported()).thenReturn(true);
+
         Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(
                 mContext, ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
         mContext.startActivity(intent);
@@ -583,7 +754,7 @@
         launchViewIntent(FOO_URL);
         FirstRunActivity secondFreActivity = waitForDifferentFirstRunActivity(firstFreActivity);
 
-        clickThroughFirstRun(secondFreActivity, SearchEnginePromoType.DONT_SHOW);
+        clickThroughFirstRun(secondFreActivity, FirstRunPagesTestCase.createWithShowAllPromos());
         verifyUrlEquals(FOO_URL, waitAndGetUriFromChromeActivity(ChromeTabbedActivity.class));
     }
 
@@ -596,7 +767,7 @@
         launchCustomTabs(FOO_URL);
         FirstRunActivity secondFreActivity = waitForDifferentFirstRunActivity(firstFreActivity);
 
-        clickThroughFirstRun(secondFreActivity, SearchEnginePromoType.DONT_SHOW);
+        clickThroughFirstRun(secondFreActivity, FirstRunPagesTestCase.createWithShowAllPromos());
         verifyUrlEquals(FOO_URL, waitAndGetUriFromChromeActivity(CustomTabActivity.class));
     }
 
@@ -609,7 +780,7 @@
         launchViewIntent(FOO_URL);
         FirstRunActivity secondFreActivity = waitForDifferentFirstRunActivity(firstFreActivity);
 
-        clickThroughFirstRun(secondFreActivity, SearchEnginePromoType.DONT_SHOW);
+        clickThroughFirstRun(secondFreActivity, FirstRunPagesTestCase.createWithShowAllPromos());
         verifyUrlEquals(FOO_URL, waitAndGetUriFromChromeActivity(ChromeTabbedActivity.class));
     }
 
@@ -676,7 +847,7 @@
                 "native never initialized.");
 
         unblockOnFlowIsKnown();
-        clickThroughFirstRun(firstRunActivity, SearchEnginePromoType.DONT_SHOW);
+        clickThroughFirstRun(firstRunActivity, new FirstRunPagesTestCase());
         verifyUrlEquals(TEST_URL, waitAndGetUriFromChromeActivity(ChromeTabbedActivity.class));
     }
 
@@ -703,13 +874,35 @@
 
         launchViewIntent(TEST_URL);
         FirstRunActivity firstRunActivity = waitForActivity(FirstRunActivity.class);
-        clickThroughFirstRun(firstRunActivity, SearchEnginePromoType.DONT_SHOW);
+        clickThroughFirstRun(firstRunActivity, FirstRunPagesTestCase.createWithShowAllPromos());
         verifyUrlEquals(TEST_URL, waitAndGetUriFromChromeActivity(ChromeTabbedActivity.class));
     }
 
+    private void setUpLocaleManagerDelegate(@SearchEnginePromoType final int searchPromoType)
+            throws Exception {
+        // Force the LocaleManager into a specific state.
+        LocaleManagerDelegate mockDelegate = new LocaleManagerDelegate() {
+            @Override
+            public int getSearchEnginePromoShowType() {
+                return searchPromoType;
+            }
+
+            @Override
+            public List<TemplateUrl> getSearchEnginesForPromoDialog(int promoType) {
+                return TemplateUrlServiceFactory.get().getTemplateUrls();
+            }
+        };
+        TestThreadUtils.runOnUiThreadBlocking(
+                () -> LocaleManager.getInstance().setDelegateForTest(mockDelegate));
+    }
+
     private void clickButton(final Activity activity, final int id, final String message) {
-        CriteriaHelper.pollUiThread(
-                () -> Criteria.checkThat(activity.findViewById(id), Matchers.notNullValue()));
+        CriteriaHelper.pollUiThread(() -> {
+            View view = activity.findViewById(id);
+            Criteria.checkThat(view, Matchers.notNullValue());
+            Criteria.checkThat(view.getVisibility(), Matchers.is(View.VISIBLE));
+            Criteria.checkThat(view.isEnabled(), Matchers.is(true));
+        });
 
         PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, () -> {
             Button button = (Button) activity.findViewById(id);
@@ -717,4 +910,185 @@
             button.performClick();
         });
     }
+
+    /** Configuration for tests that depend on showing First Run pages. */
+    static class FirstRunPagesTestCase {
+        private boolean mCctTosDisabled;
+        private @SearchEnginePromoType int mSearchPromoType = SearchEnginePromoType.DONT_SHOW;
+        private boolean mShowDataSaverPromo;
+        private boolean mShowSigninPromo;
+
+        boolean cctTosDisabled() {
+            return mCctTosDisabled;
+        }
+
+        boolean showDataSaverPromo() {
+            return mShowDataSaverPromo;
+        }
+
+        @SearchEnginePromoType
+        int searchPromoType() {
+            return mSearchPromoType;
+        }
+
+        boolean showSigninPromo() {
+            return mShowSigninPromo;
+        }
+
+        FirstRunPagesTestCase withCctTosDisabled() {
+            mCctTosDisabled = true;
+            return this;
+        }
+
+        FirstRunPagesTestCase withDataSaverPromo() {
+            mShowDataSaverPromo = true;
+            return this;
+        }
+
+        FirstRunPagesTestCase withSearchPromo() {
+            mSearchPromoType = SearchEnginePromoType.SHOW_EXISTING;
+            return this;
+        }
+
+        FirstRunPagesTestCase withSigninPromo() {
+            mShowSigninPromo = true;
+            return this;
+        }
+
+        static FirstRunPagesTestCase createWithShowAllPromos() {
+            return new FirstRunPagesTestCase()
+                    .withDataSaverPromo()
+                    .withSearchPromo()
+                    .withSigninPromo();
+        }
+    }
+
+    /**
+     * Performs basic navigation operations on First Run pages, such as checking if a given promo
+     * is current shown, moving to the next page, or going back to the previous page.
+     */
+    class FirstRunNavigationHelper {
+        private FirstRunActivity mFirstRunActivity;
+        private ScopedObserverData mScopedObserverData;
+
+        protected FirstRunNavigationHelper(FirstRunActivity firstRunActivity) {
+            mFirstRunActivity = firstRunActivity;
+            mScopedObserverData = getObserverData(mFirstRunActivity);
+        }
+
+        protected FirstRunNavigationHelper ensurePagesCreationSucceeded() throws Exception {
+            mScopedObserverData.createPostNativeAndPoliciesPageSequenceCallback.waitForCallback(
+                    "Failed to finalize the flow and create subsequent pages", 0);
+            Assert.assertEquals("Search engine name should not have been set yet", 0,
+                    mScopedObserverData.updateCachedEngineCallback.getCallCount());
+
+            return this;
+        }
+
+        protected FirstRunNavigationHelper ensureTermsOfServiceIsCurrentPage() throws Exception {
+            return waitForCurrentFragmentToMatch("Terms of Service should be the current page",
+                    Matchers.either(Matchers.instanceOf(ToSAndUMAFirstRunFragment.class))
+                            .or(Matchers.instanceOf(
+                                    TosAndUmaFirstRunFragmentWithEnterpriseSupport.class))
+                            .or(Matchers.instanceOf(SigninFirstRunFragment.class)));
+        }
+
+        protected FirstRunNavigationHelper ensureDataSaverPromoIsCurrentPage() {
+            return waitForCurrentFragmentToMatch("Data reduction promo should be the current page",
+                    Matchers.instanceOf(DataReductionProxyFirstRunFragment.class));
+        }
+
+        protected FirstRunNavigationHelper ensureDataSaverPromoNotCurrentPage() {
+            return waitForCurrentFragmentToMatch(
+                    "Data reduction promo shouldn't be the current page",
+                    Matchers.not(Matchers.instanceOf(DataReductionProxyFirstRunFragment.class)));
+        }
+
+        protected FirstRunNavigationHelper ensureDefaultSearchEnginePromoIsCurrentPage() {
+            return waitForCurrentFragmentToMatch("Search engine promo should be the current page",
+                    Matchers.instanceOf(DefaultSearchEngineFirstRunFragment.class));
+        }
+
+        protected FirstRunNavigationHelper ensureDefaultSearchEnginePromoNotCurrentPage() {
+            return waitForCurrentFragmentToMatch(
+                    "Search engine promo shouldn't be the current page",
+                    Matchers.not(Matchers.instanceOf(DefaultSearchEngineFirstRunFragment.class)));
+        }
+
+        protected FirstRunNavigationHelper ensureSigninPromoIsCurrentPage() {
+            return waitForCurrentFragmentToMatch("Sign-in promo should be the current page",
+                    Matchers.instanceOf(SyncConsentFirstRunFragment.class));
+        }
+
+        protected FirstRunNavigationHelper ensureSigninPromoNotCurrentPage() {
+            return waitForCurrentFragmentToMatch("Sign-in promo shouldn't be the current page",
+                    Matchers.not(Matchers.instanceOf(SyncConsentFirstRunFragment.class)));
+        }
+
+        protected FirstRunNavigationHelper acceptTermsOfService() throws Exception {
+            ensureTermsOfServiceIsCurrentPage();
+
+            int jumpCallCount = mScopedObserverData.jumpToPageCallback.getCallCount();
+            int acceptCallCount = mScopedObserverData.acceptTermsOfServiceCallback.getCallCount();
+
+            clickButton(mFirstRunActivity, R.id.terms_accept, "Failed to accept ToS");
+            mScopedObserverData.jumpToPageCallback.waitForCallback(
+                    "Failed to try moving to the next screen", jumpCallCount);
+            mScopedObserverData.acceptTermsOfServiceCallback.waitForCallback(
+                    "Failed to accept the ToS", acceptCallCount);
+            return this;
+        }
+
+        private FirstRunNavigationHelper acknowledgeDataSaverEnabled() throws Exception {
+            ensureDataSaverPromoIsCurrentPage();
+
+            int jumpCallCount = mScopedObserverData.jumpToPageCallback.getCallCount();
+            clickButton(mFirstRunActivity, R.id.next_button, "Failed to skip data saver");
+            mScopedObserverData.jumpToPageCallback.waitForCallback(
+                    "Failed try to move past the data saver fragment", jumpCallCount);
+
+            return this;
+        }
+
+        protected FirstRunNavigationHelper selectDefaultSearchEngine() throws Exception {
+            ensureDefaultSearchEnginePromoIsCurrentPage();
+
+            int jumpCallCount = mScopedObserverData.jumpToPageCallback.getCallCount();
+            DefaultSearchEngineDialogHelperUtils.clickOnFirstEngine(
+                    mFirstRunActivity.findViewById(android.R.id.content));
+            mScopedObserverData.jumpToPageCallback.waitForCallback(
+                    "Failed trying to move past the search engine fragment", jumpCallCount);
+
+            return this;
+        }
+
+        protected FirstRunNavigationHelper skipSigninPromo() throws Exception {
+            ensureSigninPromoIsCurrentPage();
+
+            int jumpCallCount = mScopedObserverData.jumpToPageCallback.getCallCount();
+            clickButton(mFirstRunActivity, R.id.negative_button, "Failed to skip signing-in");
+            mScopedObserverData.jumpToPageCallback.waitForCallback(
+                    "Failed trying to move past the sign in fragment", jumpCallCount);
+
+            return this;
+        }
+
+        protected FirstRunNavigationHelper goBackToPreviousPage() throws Exception {
+            int jumpCallCount = mScopedObserverData.jumpToPageCallback.getCallCount();
+            TestThreadUtils.runOnUiThreadBlocking(() -> mFirstRunActivity.onBackPressed());
+            mScopedObserverData.jumpToPageCallback.waitForCallback(
+                    "Failed go back to previous page", jumpCallCount);
+
+            return this;
+        }
+
+        private FirstRunNavigationHelper waitForCurrentFragmentToMatch(
+                String failureReason, Matcher<Object> matcher) {
+            CriteriaHelper.pollUiThread(
+                    ()
+                            -> matcher.matches(mFirstRunActivity.getCurrentFragmentForTesting()),
+                    failureReason);
+            return this;
+        }
+    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java
index a7da325..2a28ee78 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/firstrun/TosAndUmaFirstRunFragmentWithEnterpriseSupportTest.java
@@ -17,7 +17,6 @@
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
-import android.os.Bundle;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
 import android.view.View;
@@ -168,8 +167,7 @@
         mExitCount = 0;
         FirstRunActivity.setObserverForTest(new FirstRunActivity.FirstRunActivityObserver() {
             @Override
-            public void onCreatePostNativeAndPoliciesPageSequence(
-                    FirstRunActivity caller, Bundle freProperties) {}
+            public void onCreatePostNativeAndPoliciesPageSequence(FirstRunActivity caller) {}
 
             @Override
             public void onAcceptTermsOfService(FirstRunActivity caller) {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoDiscoverabilityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoDiscoverabilityTest.java
index dc10350..4efc0dc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoDiscoverabilityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoDiscoverabilityTest.java
@@ -67,7 +67,6 @@
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Batch(PER_CLASS)
-@Batch.SplitByFeature
 public class PageInfoDiscoverabilityTest {
     @ClassRule
     public static final PermissionTestRule sPermissionTestRule = new PermissionTestRule();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
index 3e8a4e5..f570bd0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -108,7 +108,6 @@
 Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, ChromeSwitches.DISABLE_STARTUP_PROMOS,
         ContentSwitches.HOST_RESOLVER_RULES + "=MAP * 127.0.0.1"})
 @Batch(PER_CLASS)
-@Batch.SplitByFeature
 public class PageInfoViewTest {
     private static final String TAG = "PageInfoViewTest";
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/PermissionInfoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/PermissionInfoTest.java
index 0d76129e..8961049 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/PermissionInfoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/PermissionInfoTest.java
@@ -14,7 +14,6 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.Batch.SplitByFeature;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Feature;
@@ -45,7 +44,6 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Batch(SiteSettingsTest.SITE_SETTINGS_BATCH_NAME)
 @DisableFeatures({ChromeFeatureList.REVERT_DSE_AUTOMATIC_PERMISSIONS})
-@SplitByFeature
 public class PermissionInfoTest {
     private static final String DSE_ORIGIN = "https://www.google.com";
     private static final String OTHER_ORIGIN = "https://www.other.com";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
index db282507..16fa31a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/FirstRunTest.java
@@ -9,7 +9,6 @@
 import android.app.Instrumentation.ActivityMonitor;
 import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
 import android.support.test.InstrumentationRegistry;
 
 import androidx.test.filters.SmallTest;
@@ -99,8 +98,7 @@
         public final CallbackHelper createPostNativeAndPoliciesPageSequence = new CallbackHelper();
 
         @Override
-        public void onCreatePostNativeAndPoliciesPageSequence(
-                FirstRunActivity caller, Bundle freProperties) {
+        public void onCreatePostNativeAndPoliciesPageSequence(FirstRunActivity caller) {
             createPostNativeAndPoliciesPageSequence.notifyCalled();
         }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateAssistContentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateAssistContentTest.java
index 5edd5254..e674c2f02 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateAssistContentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateAssistContentTest.java
@@ -39,7 +39,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(TranslateAssistContentTest.TRANSLATE_BATCH_NAME)
-@Batch.SplitByFeature
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TranslateAssistContentTest {
     public static final String TRANSLATE_BATCH_NAME = "translate_batch_name";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
index e728746a..18ebcfd 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/translate/TranslateIntentTest.java
@@ -45,7 +45,6 @@
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @Batch(TranslateAssistContentTest.TRANSLATE_BATCH_NAME)
-@Batch.SplitByFeature
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class TranslateIntentTest {
     @ClassRule
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index affddd4..62c54fa6 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -11304,12 +11304,6 @@
       <message name="IDS_WEBAUTHN_CABLE_V2_ACTIVATE_DESCRIPTION_SHORT" desc="Second line of text in an item letting the user know how they can use Chrome on their Android phone as a security key. The substring 'Use phone as a security key' refers to the string IDS_PHONE_AS_SECURITY_KEY_TEXT in Chrome on Android.">
         Open Chrome on your Android phone, and go to "Settings > Passwords > Use phone as a security key", and follow the instructions there.
       </message>
-      <message name="IDS_WEBAUTHN_CABLE_QR_TITLE" desc="Title of a dialog that contains a QR-code for the user to scan with a mobile phone app. A QR Code is a type of barcode that can be read using a smartphone's camera.">
-        Add new phone
-      </message>
-      <message name="IDS_WEBAUTHN_CABLE_QR_DESCRIPTION" desc="Description text in a dialog that contains a QR-code for the user to scan with Chrome on their Android phone. A QR Code is a type of barcode that can be read using a smartphone's camera. The substring 'Use phone as a security key' refers to the string IDS_PHONE_AS_SECURITY_KEY_TEXT in Chrome on Android.">
-        To set up an Android phone to be used as a security key with this computer for the first time, open Chrome on your phone and go to "Settings > Passwords > Use phone as a security key". Then tap "Connect new device" and scan this QR Code.
-      </message>
 
       <!-- WebAuthn authenticator PIN entry/setup -->
       <message name="IDS_WEBAUTHN_PIN_ENTRY_TITLE" desc="Title of the dialog shown when instructing the user to enter the PIN code to use a security key (an external physical device for user authentication) with their computer.">
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_DESCRIPTION.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_DESCRIPTION.png.sha1
deleted file mode 100644
index bebdb53d..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-898c0184d25296f7f62ced576b2f5c2960ebeaec
\ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_TITLE.png.sha1 b/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_TITLE.png.sha1
deleted file mode 100644
index bebdb53d..0000000
--- a/chrome/app/generated_resources_grd/IDS_WEBAUTHN_CABLE_QR_TITLE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-898c0184d25296f7f62ced576b2f5c2960ebeaec
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index a81c281..df22076 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -4680,11 +4680,6 @@
                                     kOmniboxDynamicMaxAutocompleteVariations,
                                     "OmniboxBundledExperimentV1")},
 
-    {"omnibox-webui-omnibox-popup",
-     flag_descriptions::kOmniboxWebUIOmniboxPopupName,
-     flag_descriptions::kOmniboxWebUIOmniboxPopupDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(omnibox::kWebUIOmniboxPopup)},
-
     {"memories", flag_descriptions::kMemoriesName,
      flag_descriptions::kMemoriesDescription, kOsAll,
      FEATURE_WITH_PARAMS_VALUE_TYPE(history_clusters::kMemories,
@@ -7743,6 +7738,11 @@
      FEATURE_VALUE_TYPE(extensions_features::kU2FSecurityKeyAPI)},
 #endif  // ENABLE_EXTENSIONS
 
+    {"force-major-version-to-100",
+     flag_descriptions::kForceMajorVersion100InUserAgentName,
+     flag_descriptions::kForceMajorVersion100InUserAgentDescription, kOsAll,
+     FEATURE_VALUE_TYPE(blink::features::kForceMajorVersion100InUserAgent)},
+
     // 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/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc
index 211baa0f..3eb6959 100644
--- a/chrome/browser/android/autofill_assistant/client_android.cc
+++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/autofill/android/personal_data_manager_android.h"
 #include "chrome/browser/autofill/personal_data_manager_factory.h"
 #include "chrome/browser/flags/android/chrome_feature_list.h"
+#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
@@ -56,6 +57,11 @@
 // the UI.
 const char* const kCancelActionName = "cancel";
 
+// Strings for Synthetic Field Trials.
+const char kAutofillAssistantTtsTrialName[] = "AutofillAssistantEnableTtsParam";
+const char kEnabledGroupName[] = "Enabled";
+const char kDisabledGroupName[] = "Disabled";
+
 }  // namespace
 
 static base::android::ScopedJavaLocalRef<jobject>
@@ -138,6 +144,13 @@
     AttachUI(joverlay_coordinator);
   }
 
+  // Register TTS Synthetic Field Trial.
+  ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial(
+      kAutofillAssistantTtsTrialName,
+      trigger_context->GetScriptParameters().GetEnableTts().value_or(false)
+          ? kEnabledGroupName
+          : kDisabledGroupName);
+
   DCHECK(!trigger_context->GetDirectAction());
   if (VLOG_IS_ON(2)) {
     DVLOG(2) << "Starting autofill assistant with parameters:";
diff --git a/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc b/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
index edd9acfc..af0f517 100644
--- a/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
+++ b/chrome/browser/apps/app_service/app_service_proxy_chromeos.cc
@@ -18,9 +18,9 @@
 #include "chrome/browser/apps/app_service/publishers/plugin_vm_apps.h"
 #include "chrome/browser/apps/app_service/publishers/standalone_browser_apps.h"
 #include "chrome/browser/apps/app_service/uninstall_dialog.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/child_accounts/time_limits/app_time_limit_interface.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ash/full_restore/OWNERS b/chrome/browser/ash/app_restore/OWNERS
similarity index 100%
rename from chrome/browser/ash/full_restore/OWNERS
rename to chrome/browser/ash/app_restore/OWNERS
diff --git a/chrome/browser/ash/full_restore/app_launch_handler.cc b/chrome/browser/ash/app_restore/app_launch_handler.cc
similarity index 98%
rename from chrome/browser/ash/full_restore/app_launch_handler.cc
rename to chrome/browser/ash/app_restore/app_launch_handler.cc
index 769ff58a..dad770c0 100644
--- a/chrome/browser/ash/full_restore/app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/app_launch_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/app_launch_handler.h"
 
 #include <utility>
 #include <vector>
diff --git a/chrome/browser/ash/full_restore/app_launch_handler.h b/chrome/browser/ash/app_restore/app_launch_handler.h
similarity index 93%
rename from chrome/browser/ash/full_restore/app_launch_handler.h
rename to chrome/browser/ash/app_restore/app_launch_handler.h
index 5f8960aa..2dfa5d4 100644
--- a/chrome/browser/ash/full_restore/app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/app_launch_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_APP_LAUNCH_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_APP_LAUNCH_HANDLER_H_
 
 #include "base/memory/weak_ptr.h"
 #include "components/app_restore/restore_data.h"
@@ -78,4 +78,4 @@
 
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
similarity index 98%
rename from chrome/browser/ash/full_restore/arc_app_launch_handler.cc
rename to chrome/browser/ash/app_restore/arc_app_launch_handler.cc
index 5290443..17cef152 100644
--- a/chrome/browser/ash/full_restore/arc_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
 
 #include <utility>
 #include <vector>
@@ -18,11 +18,11 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/arc_util.h"
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ash/full_restore/arc_app_launch_handler.h b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
similarity index 97%
rename from chrome/browser/ash/full_restore/arc_app_launch_handler.h
rename to chrome/browser/ash/app_restore/arc_app_launch_handler.h
index 096f094..788afed 100644
--- a/chrome/browser/ash/full_restore/arc_app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
 
 #include <list>
 #include <map>
@@ -307,4 +307,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_delegate.cc b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/arc_ghost_window_delegate.cc
rename to chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
index efb191c0e..ad54abe 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_delegate.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_ghost_window_delegate.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_delegate.h"
 
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_delegate.h b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
similarity index 89%
rename from chrome/browser/ash/full_restore/arc_ghost_window_delegate.h
rename to chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
index 7aae3a1..b6c516b 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_delegate.h
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_delegate.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
 
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
 #include "chromeos/ui/base/window_state_type.h"
 #include "components/exo/client_controlled_shell_surface.h"
 #include "ui/gfx/geometry/rect.h"
@@ -71,4 +71,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_DELEGATE_H_
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.cc b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
similarity index 95%
rename from chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.cc
rename to chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
index 8df31a5b..705cdfc 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h"
 
 #include "ash/wm/desks/desks_util.h"
-#include "chrome/browser/ash/full_restore/arc_ghost_window_delegate.h"
-#include "chrome/browser/ash/full_restore/arc_ghost_window_view.h"
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_delegate.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_view.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "components/app_restore/full_restore_utils.h"
 #include "components/app_restore/window_properties.h"
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.h b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h
similarity index 89%
rename from chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.h
rename to chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h
index 9264338..478a2dc 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.h
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
 
 #include <utility>
 
@@ -61,4 +61,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_SHELL_SURFACE_H_
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_view.cc b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
similarity index 96%
rename from chrome/browser/ash/full_restore/arc_ghost_window_view.cc
rename to chrome/browser/ash/app_restore/arc_ghost_window_view.cc
index dc10379..56086099 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_view.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_view.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_ghost_window_view.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_view.h"
 
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_chromeos.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "components/services/app_service/public/mojom/types.mojom-forward.h"
 #include "components/strings/grit/components_strings.h"
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_view.h b/chrome/browser/ash/app_restore/arc_ghost_window_view.h
similarity index 83%
rename from chrome/browser/ash/full_restore/arc_ghost_window_view.h
rename to chrome/browser/ash/app_restore/arc_ghost_window_view.h
index 9c8a988a..010cfd1 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_view.h
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_view.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
 
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
@@ -25,8 +25,7 @@
  public:
   METADATA_HEADER(ArcGhostWindowView);
 
-  explicit ArcGhostWindowView(int throbber_diameter,
-                              uint32_t theme_color);
+  explicit ArcGhostWindowView(int throbber_diameter, uint32_t theme_color);
   ArcGhostWindowView(const ArcGhostWindowView&) = delete;
   ArcGhostWindowView operator=(const ArcGhostWindowView&) = delete;
   ~ArcGhostWindowView() override;
@@ -50,4 +49,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_GHOST_WINDOW_VIEW_H_
diff --git a/chrome/browser/ash/full_restore/arc_ghost_window_view_unittest.cc b/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc
similarity index 98%
rename from chrome/browser/ash/full_restore/arc_ghost_window_view_unittest.cc
rename to chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc
index cb76b2db..65f682fb 100644
--- a/chrome/browser/ash/full_restore/arc_ghost_window_view_unittest.cc
+++ b/chrome/browser/ash/app_restore/arc_ghost_window_view_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_ghost_window_view.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_view.h"
 
 #include "base/callback_forward.h"
 #include "base/test/bind.h"
diff --git a/chrome/browser/ash/full_restore/arc_window_handler.cc b/chrome/browser/ash/app_restore/arc_window_handler.cc
similarity index 96%
rename from chrome/browser/ash/full_restore/arc_window_handler.cc
rename to chrome/browser/ash/app_restore/arc_window_handler.cc
index 4b7e1c95..1e50be1 100644
--- a/chrome/browser/ash/full_restore/arc_window_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_window_handler.cc
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
 
-#include "chrome/browser/ash/full_restore/arc_ghost_window_shell_surface.h"
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chromeos/ui/base/window_state_type.h"
 #include "components/app_restore/app_restore_data.h"
diff --git a/chrome/browser/ash/full_restore/arc_window_handler.h b/chrome/browser/ash/app_restore/arc_window_handler.h
similarity index 94%
rename from chrome/browser/ash/full_restore/arc_window_handler.h
rename to chrome/browser/ash/app_restore/arc_window_handler.h
index 9eef8a5..3cfaf7c 100644
--- a/chrome/browser/ash/full_restore/arc_window_handler.h
+++ b/chrome/browser/ash/app_restore/arc_window_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
 
 #include "base/memory/weak_ptr.h"
 #include "base/observer_list.h"
@@ -107,4 +107,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/arc_window_utils.cc b/chrome/browser/ash/app_restore/arc_window_utils.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/arc_window_utils.cc
rename to chrome/browser/ash/app_restore/arc_window_utils.cc
index d8c1012c..49f8886e4 100644
--- a/chrome/browser/ash/full_restore/arc_window_utils.cc
+++ b/chrome/browser/ash/app_restore/arc_window_utils.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
 
 #include "components/app_restore/features.h"
 #include "components/arc/arc_util.h"
diff --git a/chrome/browser/ash/full_restore/arc_window_utils.h b/chrome/browser/ash/app_restore/arc_window_utils.h
similarity index 86%
rename from chrome/browser/ash/full_restore/arc_window_utils.h
rename to chrome/browser/ash/app_restore/arc_window_utils.h
index a1a2a3f..d9fd529 100644
--- a/chrome/browser/ash/full_restore/arc_window_utils.h
+++ b/chrome/browser/ash/app_restore/arc_window_utils.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_UTILS_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_UTILS_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_UTILS_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_UTILS_H_
 
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -36,4 +36,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_ARC_WINDOW_UTILS_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_ARC_WINDOW_UTILS_H_
diff --git a/chrome/browser/ash/full_restore/arc_window_utils_unittest.cc b/chrome/browser/ash/app_restore/arc_window_utils_unittest.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/arc_window_utils_unittest.cc
rename to chrome/browser/ash/app_restore/arc_window_utils_unittest.cc
index 59a08a0..09dd5c17 100644
--- a/chrome/browser/ash/full_restore/arc_window_utils_unittest.cc
+++ b/chrome/browser/ash/app_restore/arc_window_utils_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
 
 #include "base/test/scoped_feature_list.h"
 #include "components/app_restore/features.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_app_launch_handler.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/full_restore_app_launch_handler.cc
rename to chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
index 3164c21..6374ff8 100644
--- a/chrome/browser/ash/full_restore/full_restore_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
 
 #include <set>
 #include <utility>
@@ -15,9 +15,9 @@
 #include "chrome/browser/apps/app_service/app_platform_metrics.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/full_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/login/session/user_session_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_app_launch_handler.h b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.h
similarity index 94%
rename from chrome/browser/ash/full_restore/full_restore_app_launch_handler.h
rename to chrome/browser/ash/app_restore/full_restore_app_launch_handler.h
index 983c1593..2060281 100644
--- a/chrome/browser/ash/full_restore/full_restore_app_launch_handler.h
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
 
 #include <utility>
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ash/full_restore/app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/app_launch_handler.h"
 #include "chrome/browser/sessions/session_restore_observer.h"
 #include "components/app_restore/restore_data.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -177,4 +177,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_APP_LAUNCH_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
similarity index 99%
rename from chrome/browser/ash/full_restore/full_restore_app_launch_handler_browsertest.cc
rename to chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
index cb9179a1..13ba896 100644
--- a/chrome/browser/ash/full_restore/full_restore_app_launch_handler_browsertest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
 
 #include <cstdint>
 #include <map>
@@ -23,13 +23,13 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_utils.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
+#include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
 #include "chrome/browser/ash/crosapi/browser_util.h"
-#include "chrome/browser/ash/full_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/ash/web_applications/system_web_app_integration_test.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/notifications/notification_display_service_tester.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_arc_task_handler.cc b/chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc
similarity index 89%
rename from chrome/browser/ash/full_restore/full_restore_arc_task_handler.cc
rename to chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc
index 86033d9d..5373d4b9 100644
--- a/chrome/browser/ash/full_restore/full_restore_arc_task_handler.cc
+++ b/chrome/browser/ash/app_restore/full_restore_arc_task_handler.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 
+#include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/arc_window_utils.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
-#include "chrome/browser/ash/full_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
-#include "chrome/browser/ash/full_restore/arc_window_utils.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/app_restore/full_restore_utils.h"
 
diff --git a/chrome/browser/ash/full_restore/full_restore_arc_task_handler.h b/chrome/browser/ash/app_restore/full_restore_arc_task_handler.h
similarity index 92%
rename from chrome/browser/ash/full_restore/full_restore_arc_task_handler.h
rename to chrome/browser/ash/app_restore/full_restore_arc_task_handler.h
index 844b59c..e6b50e9 100644
--- a/chrome/browser/ash/full_restore/full_restore_arc_task_handler.h
+++ b/chrome/browser/ash/app_restore/full_restore_arc_task_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
 
 #include <utility>
 
@@ -86,4 +86,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.cc b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc
similarity index 91%
rename from chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.cc
rename to chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc
index 7bc4289..62d8e0f 100644
--- a/chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.cc
+++ b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h"
 
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/arc_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs_factory.h"
 #include "components/app_restore/features.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.h b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h
similarity index 82%
rename from chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.h
rename to chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h
index 21b7160..d4158af 100644
--- a/chrome/browser/ash/full_restore/full_restore_arc_task_handler_factory.h
+++ b/chrome/browser/ash/app_restore/full_restore_arc_task_handler_factory.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
 
 #include "base/memory/singleton.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
@@ -40,4 +40,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_ARC_TASK_HANDLER_FACTORY_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_data_handler.cc b/chrome/browser/ash/app_restore/full_restore_data_handler.cc
similarity index 96%
rename from chrome/browser/ash/full_restore/full_restore_data_handler.cc
rename to chrome/browser/ash/app_restore/full_restore_data_handler.cc
index 9fdd5f8..87c29317 100644
--- a/chrome/browser/ash/full_restore/full_restore_data_handler.cc
+++ b/chrome/browser/ash/app_restore/full_restore_data_handler.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_data_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_data_handler.h"
 
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_data_handler.h b/chrome/browser/ash/app_restore/full_restore_data_handler.h
similarity index 83%
rename from chrome/browser/ash/full_restore/full_restore_data_handler.h
rename to chrome/browser/ash/app_restore/full_restore_data_handler.h
index 6b45575..5af8e5da 100644
--- a/chrome/browser/ash/full_restore/full_restore_data_handler.h
+++ b/chrome/browser/ash/app_restore/full_restore_data_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
 
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 
@@ -36,4 +36,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_DATA_HANDLER_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_prefs.cc b/chrome/browser/ash/app_restore/full_restore_prefs.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/full_restore_prefs.cc
rename to chrome/browser/ash/app_restore/full_restore_prefs.cc
index 410daaa8..f299427 100644
--- a/chrome/browser/ash/full_restore/full_restore_prefs.cc
+++ b/chrome/browser/ash/app_restore/full_restore_prefs.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/common/pref_names.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_prefs.h b/chrome/browser/ash/app_restore/full_restore_prefs.h
similarity index 90%
rename from chrome/browser/ash/full_restore/full_restore_prefs.h
rename to chrome/browser/ash/app_restore/full_restore_prefs.h
index 324bc8bb..4d7522a 100644
--- a/chrome/browser/ash/full_restore/full_restore_prefs.h
+++ b/chrome/browser/ash/app_restore/full_restore_prefs.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_PREFS_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_PREFS_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_PREFS_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_PREFS_H_
 
 class PrefRegistrySimple;
 class PrefService;
@@ -59,4 +59,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_PREFS_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_PREFS_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_prefs_unittest.cc b/chrome/browser/ash/app_restore/full_restore_prefs_unittest.cc
similarity index 98%
rename from chrome/browser/ash/full_restore/full_restore_prefs_unittest.cc
rename to chrome/browser/ash/app_restore/full_restore_prefs_unittest.cc
index c05a93a5..c680fb31 100644
--- a/chrome/browser/ash/full_restore/full_restore_prefs_unittest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_prefs_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 
 #include <memory>
 
diff --git a/chrome/browser/ash/full_restore/full_restore_service.cc b/chrome/browser/ash/app_restore/full_restore_service.cc
similarity index 97%
rename from chrome/browser/ash/full_restore/full_restore_service.cc
rename to chrome/browser/ash/app_restore/full_restore_service.cc
index a1475ba..10589a9 100644
--- a/chrome/browser/ash/full_restore/full_restore_service.cc
+++ b/chrome/browser/ash/app_restore/full_restore_service.cc
@@ -2,18 +2,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 
 #include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/notification_utils.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/string_util.h"
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_data_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
-#include "chrome/browser/ash/full_restore/full_restore_service_factory.h"
-#include "chrome/browser/ash/full_restore/new_user_restore_pref_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_data_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
+#include "chrome/browser/ash/app_restore/new_user_restore_pref_handler.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/first_run/first_run.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_service.h b/chrome/browser/ash/app_restore/full_restore_service.h
similarity index 96%
rename from chrome/browser/ash/full_restore/full_restore_service.h
rename to chrome/browser/ash/app_restore/full_restore_service.h
index 389a2bf5..a1c0e093 100644
--- a/chrome/browser/ash/full_restore/full_restore_service.h
+++ b/chrome/browser/ash/app_restore/full_restore_service.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_H_
 
 #include <memory>
 
@@ -185,4 +185,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_service_factory.cc b/chrome/browser/ash/app_restore/full_restore_service_factory.cc
similarity index 94%
rename from chrome/browser/ash/full_restore/full_restore_service_factory.cc
rename to chrome/browser/ash/app_restore/full_restore_service_factory.cc
index b86fcff3..01b9c90 100644
--- a/chrome/browser/ash/full_restore/full_restore_service_factory.cc
+++ b/chrome/browser/ash/app_restore/full_restore_service_factory.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_service_factory.h"
+#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
 
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
diff --git a/chrome/browser/ash/full_restore/full_restore_service_factory.h b/chrome/browser/ash/app_restore/full_restore_service_factory.h
similarity index 83%
rename from chrome/browser/ash/full_restore/full_restore_service_factory.h
rename to chrome/browser/ash/app_restore/full_restore_service_factory.h
index 0c00ef5a..eb09266 100644
--- a/chrome/browser/ash/full_restore/full_restore_service_factory.h
+++ b/chrome/browser/ash/app_restore/full_restore_service_factory.h
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
 
 namespace content {
@@ -50,4 +50,4 @@
 }  // namespace full_restore
 }  // namespace chromeos
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_FULL_RESTORE_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ash/full_restore/full_restore_service_unittest.cc b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
similarity index 99%
rename from chrome/browser/ash/full_restore/full_restore_service_unittest.cc
rename to chrome/browser/ash/app_restore/full_restore_service_unittest.cc
index fe24f1c..4bf5528 100644
--- a/chrome/browser/ash/full_restore/full_restore_service_unittest.cc
+++ b/chrome/browser/ash/app_restore/full_restore_service_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_switches.h"
@@ -11,8 +11,8 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/timer/timer.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
-#include "chrome/browser/ash/full_restore/full_restore_service_factory.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/first_run/first_run.h"
diff --git a/chrome/browser/ash/full_restore/new_user_restore_pref_handler.cc b/chrome/browser/ash/app_restore/new_user_restore_pref_handler.cc
similarity index 95%
rename from chrome/browser/ash/full_restore/new_user_restore_pref_handler.cc
rename to chrome/browser/ash/app_restore/new_user_restore_pref_handler.cc
index fb5fb5d..9e505034a 100644
--- a/chrome/browser/ash/full_restore/new_user_restore_pref_handler.cc
+++ b/chrome/browser/ash/app_restore/new_user_restore_pref_handler.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ash/full_restore/new_user_restore_pref_handler.h"
+#include "chrome/browser/ash/app_restore/new_user_restore_pref_handler.h"
 
 #include "ash/constants/ash_features.h"
 #include "base/bind.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 #include "chrome/browser/prefs/pref_service_syncable_util.h"
 #include "chrome/browser/profiles/profile.h"
 
diff --git a/chrome/browser/ash/full_restore/new_user_restore_pref_handler.h b/chrome/browser/ash/app_restore/new_user_restore_pref_handler.h
similarity index 92%
rename from chrome/browser/ash/full_restore/new_user_restore_pref_handler.h
rename to chrome/browser/ash/app_restore/new_user_restore_pref_handler.h
index 9f95ee9..54de333 100644
--- a/chrome/browser/ash/full_restore/new_user_restore_pref_handler.h
+++ b/chrome/browser/ash/app_restore/new_user_restore_pref_handler.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_ASH_FULL_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
-#define CHROME_BROWSER_ASH_FULL_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
+#ifndef CHROME_BROWSER_ASH_APP_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
+#define CHROME_BROWSER_ASH_APP_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
 
 #include <memory>
 
@@ -72,4 +72,4 @@
 }  // namespace full_restore
 }  // namespace ash
 
-#endif  // CHROME_BROWSER_ASH_FULL_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
+#endif  // CHROME_BROWSER_ASH_APP_RESTORE_NEW_USER_RESTORE_PREF_HANDLER_H_
diff --git a/chrome/browser/ash/arc/session/arc_service_launcher.cc b/chrome/browser/ash/arc/session/arc_service_launcher.cc
index 30d57b4..fa7d87c 100644
--- a/chrome/browser/ash/arc/session/arc_service_launcher.cc
+++ b/chrome/browser/ash/arc/session/arc_service_launcher.cc
@@ -12,6 +12,7 @@
 #include "base/check_op.h"
 #include "base/files/file_util.h"
 #include "chrome/browser/apps/app_service/publishers/arc_apps_factory.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/apps/apk_web_app_service.h"
 #include "chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h"
 #include "chrome/browser/ash/arc/adbd/arc_adbd_monitor_bridge.h"
@@ -52,7 +53,6 @@
 #include "chrome/browser/ash/arc/user_session/arc_user_session_service.h"
 #include "chrome/browser/ash/arc/video/gpu_arc_video_service_host.h"
 #include "chrome/browser/ash/arc/wallpaper/arc_wallpaper_service.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ash/login/session/user_session_manager.cc b/chrome/browser/ash/login/session/user_session_manager.cc
index 3f867f06..b8e4804 100644
--- a/chrome/browser/ash/login/session/user_session_manager.cc
+++ b/chrome/browser/ash/login/session/user_session_manager.cc
@@ -39,13 +39,13 @@
 #include "chrome/browser/about_flags.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
 #include "chrome/browser/ash/account_manager/account_manager_util.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/arc/arc_migration_guide_notification.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/base/locale_util.h"
 #include "chrome/browser/ash/child_accounts/child_policy_observer.h"
 #include "chrome/browser/ash/crosapi/browser_data_migrator.h"
 #include "chrome/browser/ash/first_run/first_run.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/ash/hats/hats_config.h"
 #include "chrome/browser/ash/login/auth/chrome_cryptohome_authenticator.h"
 #include "chrome/browser/ash/login/chrome_restart_request.h"
diff --git a/chrome/browser/ash/policy/status_collector/device_status_collector.cc b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
index 53756ba..e25ccb9 100644
--- a/chrome/browser/ash/policy/status_collector/device_status_collector.cc
+++ b/chrome/browser/ash/policy/status_collector/device_status_collector.cc
@@ -651,6 +651,23 @@
   return em::ActiveTimePeriod::SESSION_UNKNOWN;
 }
 
+// Remap GscVersion using switch-case even though the values match
+// to ensure that the compiler complains if a new value has been added.
+em::TpmVersionInfo_GscVersion ConvertTpmGscVersion(
+    tpm_manager::GscVersion gsc_version) {
+  switch (gsc_version) {
+    case tpm_manager::GscVersion::GSC_VERSION_NOT_GSC:
+      return em::TpmVersionInfo::GSC_VERSION_NOT_GSC;
+    case tpm_manager::GscVersion::GSC_VERSION_CR50:
+      return em::TpmVersionInfo::GSC_VERSION_CR50;
+    case tpm_manager::GscVersion::GSC_VERSION_TI50:
+      return em::TpmVersionInfo::GSC_VERSION_TI50;
+  }
+
+  NOTREACHED();
+  return em::TpmVersionInfo::GSC_VERSION_UNSPECIFIED;
+}
+
 }  // namespace
 
 namespace policy {
@@ -2203,7 +2220,8 @@
   tpm_version_info->set_tpm_model(tpm_version_reply_.tpm_model());
   tpm_version_info->set_firmware_version(tpm_version_reply_.firmware_version());
   tpm_version_info->set_vendor_specific(tpm_version_reply_.vendor_specific());
-
+  tpm_version_info->set_gsc_version(
+      ConvertTpmGscVersion(tpm_version_reply_.gsc_version()));
   return true;
 }
 
diff --git a/chrome/browser/ash/system_logs/reven_log_source.cc b/chrome/browser/ash/system_logs/reven_log_source.cc
index 29546cc..952c0ef 100644
--- a/chrome/browser/ash/system_logs/reven_log_source.cc
+++ b/chrome/browser/ash/system_logs/reven_log_source.cc
@@ -25,12 +25,18 @@
 constexpr char kNewlineWithIndent[] = "\n  ";
 constexpr char kKeyValueDelimiter[] = ": ";
 
+// Format for nested log entry:
+// {label}:
+//   {key1}: {value1}
+//   {key2}: {value2}
 void AddIndentedLogEntry(std::string* log,
                          const std::string& key,
                          const std::string& value) {
   base::StrAppend(log, {kNewlineWithIndent, key, kKeyValueDelimiter, value});
 }
 
+// Format for regular log entry:
+// {key1}: {value1}
 void AddLogEntry(std::string* log,
                  const std::string& key,
                  const std::string& value) {
@@ -44,7 +50,7 @@
   }
   std::vector<healthd::BluetoothAdapterInfoPtr>& adapters =
       info->bluetooth_result->get_bluetooth_adapter_info();
-  base::StrAppend(log, {"bluetoothinfo"});
+  base::StrAppend(log, {"bluetoothinfo:"});
   for (const auto& adapter : adapters) {
     AddIndentedLogEntry(log, "bluetooth_adapter_name", adapter->name);
     AddIndentedLogEntry(log, "powered", (adapter->powered ? "on" : "off"));
@@ -61,7 +67,7 @@
       info->cpu_result->get_cpu_info()->physical_cpus;
   DCHECK_GE(physical_cpus.size(), 1u);
 
-  base::StrAppend(log, {"cpuinfo"});
+  base::StrAppend(log, {"cpuinfo:"});
   for (const auto& cpu : physical_cpus) {
     AddIndentedLogEntry(log, "cpu_name", cpu->model_name.value_or(""));
   }
@@ -74,7 +80,7 @@
     return;
   }
   healthd::MemoryInfoPtr& memory_info = info->memory_result->get_memory_info();
-  base::StrAppend(log, {"meminfo"});
+  base::StrAppend(log, {"meminfo:"});
   AddIndentedLogEntry(log, "total_memory_kib",
                       base::NumberToString(memory_info->total_memory_kib));
   AddIndentedLogEntry(log, "free_memory_kib",
@@ -97,6 +103,20 @@
     AddLogEntry(log, "product_name", dmi_info->product_name.value_or(""));
     AddLogEntry(log, "product_version", dmi_info->product_version.value_or(""));
   }
+
+  base::StrAppend(log, {"biosinfo:"});
+  if (!dmi_info.is_null()) {
+    AddIndentedLogEntry(log, "bios_version",
+                        dmi_info->bios_version.value_or(""));
+  }
+  healthd::OsInfoPtr& os_info =
+      info->system_result_v2->get_system_info_v2()->os_info;
+  if (!os_info.is_null()) {
+    AddIndentedLogEntry(
+        log, "uefi",
+        (os_info->boot_mode == healthd::BootMode::kCrosEfi) ? "true" : "false");
+  }
+  base::StrAppend(log, {"\n"});
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/system_logs/reven_log_source_unittest.cc b/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
index ddc2ebd..27af411 100644
--- a/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
+++ b/chrome/browser/ash/system_logs/reven_log_source_unittest.cc
@@ -12,6 +12,7 @@
 #include "chromeos/dbus/cros_healthd/fake_cros_healthd_client.h"
 #include "chromeos/services/cros_healthd/public/cpp/service_connection.h"
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd.mojom.h"
+#include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom-shared.h"
 #include "chromeos/services/cros_healthd/public/mojom/cros_healthd_probe.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -97,10 +98,12 @@
 }
 
 void SetSystemInfoV2(healthd::TelemetryInfoPtr& telemetry_info,
+                     healthd::OsInfoPtr os_info,
                      healthd::DmiInfoPtr dmi_info) {
   auto system_info2 = healthd::SystemInfoV2::New();
-  system_info2->os_info = healthd::OsInfo::New();
-  system_info2->os_info->os_version = healthd::OsVersion::New();
+  if (os_info) {
+    system_info2->os_info = std::move(os_info);
+  }
 
   if (dmi_info) {
     system_info2->dmi_info = std::move(dmi_info);
@@ -109,12 +112,20 @@
       healthd::SystemResultV2::NewSystemInfoV2(std::move(system_info2));
 }
 
+healthd::OsInfoPtr CreateOsInfo(healthd::BootMode boot_mode) {
+  healthd::OsInfoPtr os_info = healthd::OsInfo::New();
+  os_info->os_version = healthd::OsVersion::New();
+  os_info->boot_mode = boot_mode;
+  return os_info;
+}
+
 healthd::DmiInfoPtr CreateDmiInfo() {
   healthd::DmiInfoPtr dmi_info = healthd::DmiInfo::New();
   dmi_info->sys_vendor = absl::optional<std::string>("LENOVO");
   dmi_info->product_name = absl::optional<std::string>("20U9001PUS");
   dmi_info->product_version =
       absl::optional<std::string>("ThinkPad X1 Carbon Gen 8");
+  dmi_info->bios_version = absl::optional<std::string>("N2WET26W (1.16 )");
   return dmi_info;
 }
 
@@ -149,6 +160,24 @@
     return result;
   }
 
+  void VerifyBiosBootMode(healthd::BootMode boot_mode,
+                          const std::string& expected) {
+    auto info = healthd::TelemetryInfo::New();
+    auto os_info = CreateOsInfo(boot_mode);
+    auto dmi_info = healthd::DmiInfo::New();
+    SetSystemInfoV2(info, std::move(os_info), std::move(dmi_info));
+    ash::cros_healthd::FakeCrosHealthdClient::Get()
+        ->SetProbeTelemetryInfoResponseForTesting(info);
+
+    std::unique_ptr<SystemLogsResponse> response = Fetch();
+    ASSERT_NE(response, nullptr);
+    const auto revenlog_iter = response->find(kRevenLogKey);
+    ASSERT_NE(revenlog_iter, response->end());
+
+    EXPECT_THAT(revenlog_iter->second, HasSubstr("biosinfo:\n"));
+    EXPECT_THAT(revenlog_iter->second, HasSubstr(expected));
+  }
+
  protected:
   base::test::TaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@@ -182,9 +211,10 @@
   const auto revenlog_iter = response->find(kRevenLogKey);
   ASSERT_NE(revenlog_iter, response->end());
 
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("bluetoothinfo:\n"));
   EXPECT_THAT(revenlog_iter->second,
-              HasSubstr("bluetooth_adapter_name: BlueZ 5.54"));
-  EXPECT_THAT(revenlog_iter->second, HasSubstr("powered: off"));
+              HasSubstr("\n  bluetooth_adapter_name: BlueZ 5.54"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("\n  powered: off"));
 }
 
 TEST_F(RevenLogSourceTest, FetchBluetoothAdapterInfoFailure) {
@@ -214,8 +244,10 @@
   const auto revenlog_iter = response->find(kRevenLogKey);
   ASSERT_NE(revenlog_iter, response->end());
 
-  EXPECT_THAT(revenlog_iter->second,
-              HasSubstr("cpu_name: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("cpuinfo:\n"));
+  EXPECT_THAT(
+      revenlog_iter->second,
+      HasSubstr("\n  cpu_name: Intel(R) Core(TM) i5-10210U CPU @ 1.60GHz"));
 }
 
 TEST_F(RevenLogSourceTest, FetchCpuInfoFailure) {
@@ -243,9 +275,11 @@
   const auto revenlog_iter = response->find(kRevenLogKey);
   ASSERT_NE(revenlog_iter, response->end());
 
-  EXPECT_THAT(revenlog_iter->second, HasSubstr("total_memory_kib: 2048"));
-  EXPECT_THAT(revenlog_iter->second, HasSubstr("free_memory_kib: 1024"));
-  EXPECT_THAT(revenlog_iter->second, HasSubstr("available_memory_kib: 512"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("meminfo:\n"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("\n  total_memory_kib: 2048"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("\n  free_memory_kib: 1024"));
+  EXPECT_THAT(revenlog_iter->second,
+              HasSubstr("\n  available_memory_kib: 512"));
 }
 
 TEST_F(RevenLogSourceTest, FetchMemoryInfoFailure) {
@@ -266,8 +300,9 @@
 
 TEST_F(RevenLogSourceTest, FetchDmiInfoWithValues) {
   auto info = healthd::TelemetryInfo::New();
+  auto os_info = CreateOsInfo(healthd::BootMode::kUnknown);
   auto dmi_info = CreateDmiInfo();
-  SetSystemInfoV2(info, std::move(dmi_info));
+  SetSystemInfoV2(info, std::move(os_info), std::move(dmi_info));
   ash::cros_healthd::FakeCrosHealthdClient::Get()
       ->SetProbeTelemetryInfoResponseForTesting(info);
 
@@ -280,12 +315,17 @@
   EXPECT_THAT(revenlog_iter->second, HasSubstr("product_name: 20U9001PUS"));
   EXPECT_THAT(revenlog_iter->second,
               HasSubstr("product_version: ThinkPad X1 Carbon Gen 8"));
+
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("biosinfo:\n"));
+  EXPECT_THAT(revenlog_iter->second,
+              HasSubstr("\n  bios_version: N2WET26W (1.16 )"));
 }
 
 TEST_F(RevenLogSourceTest, FetchDmiInfoWithoutValues) {
   auto info = healthd::TelemetryInfo::New();
+  auto os_info = CreateOsInfo(healthd::BootMode::kCrosEfi);
   auto dmi_info = healthd::DmiInfo::New();
-  SetSystemInfoV2(info, std::move(dmi_info));
+  SetSystemInfoV2(info, std::move(os_info), std::move(dmi_info));
   ash::cros_healthd::FakeCrosHealthdClient::Get()
       ->SetProbeTelemetryInfoResponseForTesting(info);
 
@@ -297,6 +337,25 @@
   EXPECT_THAT(revenlog_iter->second, HasSubstr("product_vendor: \n"));
   EXPECT_THAT(revenlog_iter->second, HasSubstr("product_name: \n"));
   EXPECT_THAT(revenlog_iter->second, HasSubstr("product_version: \n"));
+
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("biosinfo:\n"));
+  EXPECT_THAT(revenlog_iter->second, HasSubstr("\n  bios_version: \n"));
+}
+
+TEST_F(RevenLogSourceTest, BiosBootMode_kCrosEfi) {
+  VerifyBiosBootMode(healthd::BootMode::kCrosEfi, "\n  uefi: true");
+}
+
+TEST_F(RevenLogSourceTest, BiosBootMode_kUnknown) {
+  VerifyBiosBootMode(healthd::BootMode::kUnknown, "\n  uefi: false");
+}
+
+TEST_F(RevenLogSourceTest, BiosBootMode_kCrosSecure) {
+  VerifyBiosBootMode(healthd::BootMode::kCrosSecure, "\n  uefi: false");
+}
+
+TEST_F(RevenLogSourceTest, BiosBootMode_kCrosLegacy) {
+  VerifyBiosBootMode(healthd::BootMode::kCrosLegacy, "\n  uefi: false");
 }
 
 }  // namespace system_logs
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 867b78c..c4cf728 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -608,6 +608,36 @@
     "../ash/app_mode/web_app/web_kiosk_app_launcher.h",
     "../ash/app_mode/web_app/web_kiosk_app_manager.cc",
     "../ash/app_mode/web_app/web_kiosk_app_manager.h",
+    "../ash/app_restore/app_launch_handler.cc",
+    "../ash/app_restore/app_launch_handler.h",
+    "../ash/app_restore/arc_app_launch_handler.cc",
+    "../ash/app_restore/arc_app_launch_handler.h",
+    "../ash/app_restore/arc_ghost_window_delegate.cc",
+    "../ash/app_restore/arc_ghost_window_delegate.h",
+    "../ash/app_restore/arc_ghost_window_shell_surface.cc",
+    "../ash/app_restore/arc_ghost_window_shell_surface.h",
+    "../ash/app_restore/arc_ghost_window_view.cc",
+    "../ash/app_restore/arc_ghost_window_view.h",
+    "../ash/app_restore/arc_window_handler.cc",
+    "../ash/app_restore/arc_window_handler.h",
+    "../ash/app_restore/arc_window_utils.cc",
+    "../ash/app_restore/arc_window_utils.h",
+    "../ash/app_restore/full_restore_app_launch_handler.cc",
+    "../ash/app_restore/full_restore_app_launch_handler.h",
+    "../ash/app_restore/full_restore_arc_task_handler.cc",
+    "../ash/app_restore/full_restore_arc_task_handler.h",
+    "../ash/app_restore/full_restore_arc_task_handler_factory.cc",
+    "../ash/app_restore/full_restore_arc_task_handler_factory.h",
+    "../ash/app_restore/full_restore_data_handler.cc",
+    "../ash/app_restore/full_restore_data_handler.h",
+    "../ash/app_restore/full_restore_prefs.cc",
+    "../ash/app_restore/full_restore_prefs.h",
+    "../ash/app_restore/full_restore_service.cc",
+    "../ash/app_restore/full_restore_service.h",
+    "../ash/app_restore/full_restore_service_factory.cc",
+    "../ash/app_restore/full_restore_service_factory.h",
+    "../ash/app_restore/new_user_restore_pref_handler.cc",
+    "../ash/app_restore/new_user_restore_pref_handler.h",
     "../ash/apps/apk_web_app_installer.cc",
     "../ash/apps/apk_web_app_installer.h",
     "../ash/apps/apk_web_app_service.cc",
@@ -1402,36 +1432,6 @@
     "../ash/first_run/drive_first_run_controller.h",
     "../ash/first_run/first_run.cc",
     "../ash/first_run/first_run.h",
-    "../ash/full_restore/app_launch_handler.cc",
-    "../ash/full_restore/app_launch_handler.h",
-    "../ash/full_restore/arc_app_launch_handler.cc",
-    "../ash/full_restore/arc_app_launch_handler.h",
-    "../ash/full_restore/arc_ghost_window_delegate.cc",
-    "../ash/full_restore/arc_ghost_window_delegate.h",
-    "../ash/full_restore/arc_ghost_window_shell_surface.cc",
-    "../ash/full_restore/arc_ghost_window_shell_surface.h",
-    "../ash/full_restore/arc_ghost_window_view.cc",
-    "../ash/full_restore/arc_ghost_window_view.h",
-    "../ash/full_restore/arc_window_handler.cc",
-    "../ash/full_restore/arc_window_handler.h",
-    "../ash/full_restore/arc_window_utils.cc",
-    "../ash/full_restore/arc_window_utils.h",
-    "../ash/full_restore/full_restore_app_launch_handler.cc",
-    "../ash/full_restore/full_restore_app_launch_handler.h",
-    "../ash/full_restore/full_restore_arc_task_handler.cc",
-    "../ash/full_restore/full_restore_arc_task_handler.h",
-    "../ash/full_restore/full_restore_arc_task_handler_factory.cc",
-    "../ash/full_restore/full_restore_arc_task_handler_factory.h",
-    "../ash/full_restore/full_restore_data_handler.cc",
-    "../ash/full_restore/full_restore_data_handler.h",
-    "../ash/full_restore/full_restore_prefs.cc",
-    "../ash/full_restore/full_restore_prefs.h",
-    "../ash/full_restore/full_restore_service.cc",
-    "../ash/full_restore/full_restore_service.h",
-    "../ash/full_restore/full_restore_service_factory.cc",
-    "../ash/full_restore/full_restore_service_factory.h",
-    "../ash/full_restore/new_user_restore_pref_handler.cc",
-    "../ash/full_restore/new_user_restore_pref_handler.h",
     "../ash/guest_os/guest_os_diagnostics_builder.cc",
     "../ash/guest_os/guest_os_diagnostics_builder.h",
     "../ash/guest_os/guest_os_external_protocol_handler.cc",
@@ -3700,6 +3700,10 @@
     "../ash/app_mode/kiosk_app_launch_error_unittest.cc",
     "../ash/app_mode/startup_app_launcher_unittest.cc",
     "../ash/app_mode/web_app/web_kiosk_app_launcher_unittest.cc",
+    "../ash/app_restore/arc_ghost_window_view_unittest.cc",
+    "../ash/app_restore/arc_window_utils_unittest.cc",
+    "../ash/app_restore/full_restore_prefs_unittest.cc",
+    "../ash/app_restore/full_restore_service_unittest.cc",
     "../ash/apps/apk_web_app_installer_unittest.cc",
     "../ash/apps/metrics/intent_handling_metrics_unittest.cc",
     "../ash/arc/accessibility/accessibility_info_data_wrapper_unittest.cc",
@@ -3941,10 +3945,6 @@
     "../ash/file_system_provider/scoped_file_opener_unittest.cc",
     "../ash/file_system_provider/service_unittest.cc",
     "../ash/file_system_provider/throttled_file_system_unittest.cc",
-    "../ash/full_restore/arc_ghost_window_view_unittest.cc",
-    "../ash/full_restore/arc_window_utils_unittest.cc",
-    "../ash/full_restore/full_restore_prefs_unittest.cc",
-    "../ash/full_restore/full_restore_service_unittest.cc",
     "../ash/guest_os/guest_os_diagnostics_builder_unittest.cc",
     "../ash/guest_os/guest_os_external_protocol_handler_unittest.cc",
     "../ash/guest_os/guest_os_mime_types_service_unittest.cc",
diff --git a/chrome/browser/chromeos/browser_context_keyed_service_factories.cc b/chrome/browser/chromeos/browser_context_keyed_service_factories.cc
index 08ebe875..ebaa2ad 100644
--- a/chrome/browser/chromeos/browser_context_keyed_service_factories.cc
+++ b/chrome/browser/chromeos/browser_context_keyed_service_factories.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/browser_context_keyed_service_factories.h"
 
+#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
 #include "chrome/browser/ash/arc/accessibility/arc_accessibility_helper_bridge.h"
 #include "chrome/browser/ash/authpolicy/authpolicy_credentials_manager.h"
 #include "chrome/browser/ash/bluetooth/debug_logs_manager_factory.h"
@@ -12,7 +13,6 @@
 #include "chrome/browser/ash/crostini/crostini_engagement_metrics_service.h"
 #include "chrome/browser/ash/file_manager/volume_manager_factory.h"
 #include "chrome/browser/ash/file_system_provider/service_factory.h"
-#include "chrome/browser/ash/full_restore/full_restore_service_factory.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/ash/kerberos/kerberos_credentials_manager_factory.h"
 #include "chrome/browser/ash/login/easy_unlock/easy_unlock_service_factory.h"
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
index 8527a9f..040123e 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #include "components/sessions/content/session_tab_helper.h"
-#include "content/public/browser/notification_service.h"
 #include "extensions/browser/api/declarative_net_request/constants.h"
 #include "extensions/browser/api/declarative_net_request/utils.h"
 #include "extensions/browser/event_router.h"
@@ -39,7 +38,6 @@
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_util.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/common/api/extension_action/action_info.h"
 #include "extensions/common/error_utils.h"
 #include "extensions/common/feature_switch.h"
@@ -578,6 +576,7 @@
 }
 
 BrowserActionOpenPopupFunction::BrowserActionOpenPopupFunction() = default;
+BrowserActionOpenPopupFunction::~BrowserActionOpenPopupFunction() = default;
 
 ExtensionFunction::ResponseAction BrowserActionOpenPopupFunction::Run() {
   // We only allow the popup in the active window.
@@ -609,8 +608,7 @@
   // If the extension is spanning, then extension hosts are created with the
   // original profile, and if it's split, then we know the api call came from
   // the right profile.
-  registrar_.Add(this, NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-                 content::Source<Profile>(profile));
+  host_registry_observation_.Observe(ExtensionHostRegistry::Get(profile));
 
   // Set a timeout for waiting for the notification that the popup is loaded.
   // Waiting is required so that the popup view can be retrieved by the custom
@@ -623,6 +621,15 @@
   return RespondLater();
 }
 
+void BrowserActionOpenPopupFunction::OnBrowserContextShutdown() {
+  // No point in responding at this point (the context is gone). However, we
+  // need to explicitly remove the ExtensionHostRegistry observation, since the
+  // ExtensionHostRegistry's lifetime is tied to the BrowserContext. Otherwise,
+  // this would cause a UAF when the observation is destructed as part of this
+  // instance's destruction.
+  host_registry_observation_.Reset();
+}
+
 void BrowserActionOpenPopupFunction::OpenPopupTimedOut() {
   if (did_respond())
     return;
@@ -631,21 +638,18 @@
   Respond(Error(kOpenPopupError));
 }
 
-void BrowserActionOpenPopupFunction::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, type);
+void BrowserActionOpenPopupFunction::OnExtensionHostCompletedFirstLoad(
+    content::BrowserContext* browser_context,
+    ExtensionHost* host) {
   if (did_respond())
     return;
 
-  ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
   if (host->extension_host_type() != mojom::ViewType::kExtensionPopup ||
       host->extension()->id() != extension_->id())
     return;
 
   Respond(NoArguments());
-  registrar_.RemoveAll();
+  host_registry_observation_.Reset();
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.h b/chrome/browser/extensions/api/extension_action/extension_action_api.h
index 1fa5f9d7..5320ff09 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.h
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.h
@@ -9,12 +9,12 @@
 
 #include "base/macros.h"
 #include "base/observer_list.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
+#include "base/scoped_observation.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
 #include "extensions/browser/extension_action.h"
 #include "extensions/browser/extension_event_histogram_value.h"
 #include "extensions/browser/extension_function.h"
+#include "extensions/browser/extension_host_registry.h"
 #include "third_party/skia/include/core/SkColor.h"
 
 namespace base {
@@ -29,6 +29,7 @@
 class Browser;
 
 namespace extensions {
+class ExtensionHost;
 class ExtensionPrefs;
 
 class ExtensionActionAPI : public BrowserContextKeyedAPI {
@@ -454,24 +455,29 @@
 };
 
 class BrowserActionOpenPopupFunction : public ExtensionFunction,
-                                       public content::NotificationObserver {
+                                       public ExtensionHostRegistry::Observer {
  public:
   DECLARE_EXTENSION_FUNCTION("browserAction.openPopup",
                              BROWSERACTION_OPEN_POPUP)
   BrowserActionOpenPopupFunction();
 
  private:
-  ~BrowserActionOpenPopupFunction() override {}
+  ~BrowserActionOpenPopupFunction() override;
 
   // ExtensionFunction:
   ResponseAction Run() override;
+  void OnBrowserContextShutdown() override;
 
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
+  // ExtensionHostRegistry::Observer:
+  void OnExtensionHostCompletedFirstLoad(
+      content::BrowserContext* browser_context,
+      ExtensionHost* host) override;
+
   void OpenPopupTimedOut();
 
-  content::NotificationRegistrar registrar_;
+  base::ScopedObservation<ExtensionHostRegistry,
+                          ExtensionHostRegistry::Observer>
+      host_registry_observation_{this};
 
   DISALLOW_COPY_AND_ASSIGN(BrowserActionOpenPopupFunction);
 };
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc
index 46a4067..36f3ca6 100644
--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -62,8 +62,8 @@
 #include "ash/constants/ash_pref_names.h"
 #include "ash/constants/ash_pref_names.h"  // nogncheck
 #include "ash/public/cpp/ambient/ambient_prefs.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/crostini/crostini_pref_names.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/guest_os/guest_os_pref_names.h"
 #include "chrome/browser/ash/ownership/owner_settings_service_ash.h"
 #include "chrome/browser/ash/ownership/owner_settings_service_ash_factory.h"
diff --git a/chrome/browser/extensions/extension_messages_apitest.cc b/chrome/browser/extensions/extension_messages_apitest.cc
index ac8b453a..5a3d474 100644
--- a/chrome/browser/extensions/extension_messages_apitest.cc
+++ b/chrome/browser/extensions/extension_messages_apitest.cc
@@ -25,7 +25,6 @@
 #include "base/task/post_task.h"
 #include "base/values.h"
 #include "build/build_config.h"
-#include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/extensions/api/messaging/incognito_connectability.h"
 #include "chrome/browser/extensions/browsertest_util.h"
 #include "chrome/browser/extensions/extension_apitest.h"
@@ -41,8 +40,6 @@
 #include "components/infobars/content/content_infobar_manager.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/test/browser_test.h"
@@ -50,6 +47,7 @@
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/browsertest_util.h"
 #include "extensions/browser/event_router.h"
+#include "extensions/browser/extension_host_registry.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
@@ -70,12 +68,11 @@
 namespace extensions {
 namespace {
 
-class MessageSender : public content::NotificationObserver {
+class MessageSender : public ExtensionHostRegistry::Observer {
  public:
-  MessageSender() {
-    registrar_.Add(this,
-                   extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-                   content::NotificationService::AllSources());
+  explicit MessageSender(content::BrowserContext* browser_context) {
+    host_registry_observation_.Observe(
+        ExtensionHostRegistry::Get(browser_context));
   }
 
  private:
@@ -92,44 +89,38 @@
 
   static std::unique_ptr<Event> BuildEvent(
       std::unique_ptr<base::ListValue> event_args,
-      Profile* profile,
+      content::BrowserContext* browser_context,
       GURL event_url) {
-    auto event =
-        std::make_unique<Event>(events::TEST_ON_MESSAGE, "test.onMessage",
-                                std::move(*event_args).TakeList(), profile);
-    event->event_url = event_url;
+    auto event = std::make_unique<Event>(
+        events::TEST_ON_MESSAGE, "test.onMessage",
+        std::move(*event_args).TakeList(), browser_context);
+    event->event_url = std::move(event_url);
     return event;
   }
 
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override {
-    DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-              type);
-    EventRouter* event_router =
-        EventRouter::Get(content::Source<Profile>(source).ptr());
+  // ExtensionHostRegistry::Observer:
+  void OnExtensionHostCompletedFirstLoad(
+      content::BrowserContext* browser_context,
+      ExtensionHost* extension_host) override {
+    EventRouter* event_router = EventRouter::Get(browser_context);
 
     // Sends four messages to the extension. All but the third message sent
     // from the origin http://b.com/ are supposed to arrive.
     event_router->BroadcastEvent(BuildEvent(
-        BuildEventArguments(false, "no restriction"),
-        content::Source<Profile>(source).ptr(),
-        GURL()));
+        BuildEventArguments(false, "no restriction"), browser_context, GURL()));
+    event_router->BroadcastEvent(
+        BuildEvent(BuildEventArguments(false, "http://a.com/"), browser_context,
+                   GURL("http://a.com/")));
+    event_router->BroadcastEvent(
+        BuildEvent(BuildEventArguments(false, "http://b.com/"), browser_context,
+                   GURL("http://b.com/")));
     event_router->BroadcastEvent(BuildEvent(
-        BuildEventArguments(false, "http://a.com/"),
-        content::Source<Profile>(source).ptr(),
-        GURL("http://a.com/")));
-    event_router->BroadcastEvent(BuildEvent(
-        BuildEventArguments(false, "http://b.com/"),
-        content::Source<Profile>(source).ptr(),
-        GURL("http://b.com/")));
-    event_router->BroadcastEvent(BuildEvent(
-        BuildEventArguments(true, "last message"),
-        content::Source<Profile>(source).ptr(),
-        GURL()));
+        BuildEventArguments(true, "last message"), browser_context, GURL()));
   }
 
-  content::NotificationRegistrar registrar_;
+  base::ScopedObservation<ExtensionHostRegistry,
+                          ExtensionHostRegistry::Observer>
+      host_registry_observation_{this};
 };
 
 class MessagingApiTest : public ExtensionApiTest {
@@ -188,7 +179,7 @@
 // Tests that messages with event_urls are only passed to extensions with
 // appropriate permissions.
 IN_PROC_BROWSER_TEST_F(MessagingApiTest, MessagingEventURL) {
-  MessageSender sender;
+  MessageSender sender(profile());
   ASSERT_TRUE(RunExtensionTest("messaging/event_url")) << message_;
 }
 
diff --git a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
index 7bf86b65d..0f13ae7 100644
--- a/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_chromeos_unittest.cc
@@ -39,6 +39,7 @@
 #include "content/public/browser/notification_service.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/extension_registry.h"
+#include "testing/gtest/include/gtest/gtest.h"
 
 namespace extensions {
 
@@ -249,10 +250,34 @@
   TestingBrowserProcess::GetGlobal()->SetProfileManager(nullptr);
 }
 
+enum class SyncSettingsCategorization { kEnabled, kDisabled };
+
+class ExternalProviderImplChromeOSSyncCategorizationTest
+    : public ExternalProviderImplChromeOSTest,
+      public ::testing::WithParamInterface<SyncSettingsCategorization> {
+ public:
+  ExternalProviderImplChromeOSSyncCategorizationTest() {
+    switch (GetParam()) {
+      case SyncSettingsCategorization::kEnabled:
+        feature_list_.InitAndEnableFeature(
+            chromeos::features::kSyncSettingsCategorization);
+        break;
+      case SyncSettingsCategorization::kDisabled:
+        feature_list_.InitAndDisableFeature(
+            chromeos::features::kSyncSettingsCategorization);
+        break;
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
 // User signed in, sync service started, install app when priority sync is
 // completed.
 // TODO(crbug.com/1177118) Re-enable test
-TEST_F(ExternalProviderImplChromeOSTest, DISABLED_PriorityCompleted) {
+TEST_P(ExternalProviderImplChromeOSSyncCategorizationTest,
+       DISABLED_PriorityCompleted) {
   InitServiceWithExternalProviders(true);
 
   // User is logged in.
@@ -272,7 +297,7 @@
   // SyncSettingsCategorization makes ExternalPrefLoader wait for OS priority
   // prefs.
   syncer::ModelType priority_pref_type =
-      chromeos::features::IsSyncSettingsCategorizationEnabled()
+      GetParam() == SyncSettingsCategorization::kEnabled
           ? syncer::OS_PRIORITY_PREFERENCES
           : syncer::PRIORITY_PREFERENCES;
 
@@ -291,6 +316,11 @@
   EXPECT_TRUE(registry()->GetInstalledExtension(kStandaloneAppId));
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         ExternalProviderImplChromeOSSyncCategorizationTest,
+                         testing::Values(SyncSettingsCategorization::kDisabled,
+                                         SyncSettingsCategorization::kEnabled));
+
 // Validate the external providers enabled in the Chrome App Kiosk session. The
 // expected number should be 3.
 // - |policy_provider|.
diff --git a/chrome/browser/feed/android/BUILD.gn b/chrome/browser/feed/android/BUILD.gn
index 846d18b..d9c809e4 100644
--- a/chrome/browser/feed/android/BUILD.gn
+++ b/chrome/browser/feed/android/BUILD.gn
@@ -12,8 +12,10 @@
     "java/src/org/chromium/chrome/browser/feed/FeedImageFetchClient.java",
     "java/src/org/chromium/chrome/browser/feed/FeedReliabilityLoggingBridge.java",
     "java/src/org/chromium/chrome/browser/feed/FeedServiceBridge.java",
+    "java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java",
     "java/src/org/chromium/chrome/browser/feed/FeedUma.java",
     "java/src/org/chromium/chrome/browser/feed/VideoPreviewsType.java",
+    "java/src/org/chromium/chrome/browser/feed/componentinterfaces/SurfaceCoordinator.java",
     "java/src/org/chromium/chrome/browser/feed/settings/FeedAutoplaySettingsFragment.java",
     "java/src/org/chromium/chrome/browser/feed/settings/RadioButtonGroupVideoPreviewsPreference.java",
     "java/src/org/chromium/chrome/browser/feed/webfeed/ShadowedClickableTextBubble.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java
similarity index 63%
rename from chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java
rename to chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java
index 2b2886d7..02aa62296 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/FeedSurfaceTracker.java
@@ -6,7 +6,8 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.feed.v2.FeedServiceBridgeDelegateImpl;
+import org.chromium.base.ObserverList;
+import org.chromium.chrome.browser.feed.componentinterfaces.SurfaceCoordinator;
 import org.chromium.chrome.browser.xsurface.ProcessScope;
 
 import java.util.ArrayList;
@@ -16,7 +17,13 @@
 /**
  * Tracker class for various feed surfaces.
  */
-public class FeedSurfaceTracker {
+public class FeedSurfaceTracker implements SurfaceCoordinator.Observer {
+    /** Feed surface tracker observer. */
+    public interface Observer {
+        // Called any time a Feed surface is opened.
+        void surfaceOpened();
+    }
+
     private static FeedSurfaceTracker sSurfaceTracker;
 
     // We avoid attaching surfaces until after |startup()| is called. This ensures that
@@ -24,20 +31,21 @@
     private boolean mStartupCalled;
 
     private boolean mSetServiceBridgeDelegate;
+    private ObserverList<Observer> mObservers = new ObserverList<>();
 
     /**
      * Initializes the FeedServiceBridge. We do this once at startup, either in startup(), or
      * in FeedStreamSurface's constructor, whichever comes first.
      */
-    void initServiceBridge() {
+    void initServiceBridge(FeedServiceBridge.Delegate delegate) {
         if (mSetServiceBridgeDelegate) return;
         mSetServiceBridgeDelegate = true;
-        FeedServiceBridge.setDelegate(new FeedServiceBridgeDelegateImpl());
+        FeedServiceBridge.setDelegate(delegate);
     }
 
     // Tracks all the instances of FeedSurfaceCoordinator.
     @VisibleForTesting
-    HashSet<FeedSurfaceCoordinator> mCoordinators;
+    HashSet<SurfaceCoordinator> mCoordinators;
 
     public static FeedSurfaceTracker getInstance() {
         if (sSurfaceTracker == null) {
@@ -61,39 +69,50 @@
         mStartupCalled = true;
         FeedServiceBridge.startup();
         if (mCoordinators != null) {
-            for (FeedSurfaceCoordinator coordinator : mCoordinators) {
+            for (SurfaceCoordinator coordinator : mCoordinators) {
                 coordinator.onSurfaceOpened();
             }
         }
     }
 
+    public void addObserver(Observer observer) {
+        mObservers.addObserver(observer);
+    }
+
+    public void removeObserver(Observer observer) {
+        mObservers.removeObserver(observer);
+    }
+
     boolean isStartupCalled() {
         return mStartupCalled;
     }
 
-    void untrackSurface(FeedSurfaceCoordinator coordinator) {
-        if (mCoordinators != null) {
-            mCoordinators.remove(coordinator);
+    void untrackSurface(SurfaceCoordinator coordinator) {
+        if (mCoordinators == null) {
+            return;
         }
+        mCoordinators.remove(coordinator);
+        coordinator.removeObserver(this);
     }
 
-    void trackSurface(FeedSurfaceCoordinator coordinator) {
+    void trackSurface(SurfaceCoordinator coordinator) {
         if (mCoordinators == null) {
             mCoordinators = new HashSet<>();
         }
         mCoordinators.add(coordinator);
+        coordinator.addObserver(this);
     }
 
     /** Clears all inactive coordinators and resets account. */
     public void clearAll() {
         if (mCoordinators == null) return;
 
-        List<FeedSurfaceCoordinator> activeCoordinators = new ArrayList<>();
-        for (FeedSurfaceCoordinator coordinator : mCoordinators) {
+        List<SurfaceCoordinator> activeCoordinators = new ArrayList<>();
+        for (SurfaceCoordinator coordinator : mCoordinators) {
             if (coordinator.isActive()) activeCoordinators.add(coordinator);
         }
 
-        for (FeedSurfaceCoordinator coordinator : activeCoordinators) {
+        for (SurfaceCoordinator coordinator : activeCoordinators) {
             coordinator.onSurfaceClosed();
         }
 
@@ -102,11 +121,18 @@
             processScope.resetAccount();
         }
 
-        for (FeedSurfaceCoordinator coordinator : activeCoordinators) {
+        for (SurfaceCoordinator coordinator : activeCoordinators) {
             coordinator.onSurfaceOpened();
         }
     }
 
+    @Override
+    public void surfaceOpened() {
+        for (Observer observer : mObservers) {
+            observer.surfaceOpened();
+        }
+    }
+
     @VisibleForTesting
     public void resetForTest() {
         mStartupCalled = false;
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/README.md b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/README.md
new file mode 100644
index 0000000..6716510
--- /dev/null
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/README.md
@@ -0,0 +1,3 @@
+We are in the process move migrating code from chrome_java to this Feed java
+library. This directory contains interfaces needed in the interim, but will
+unnecessary when the migration is complete.
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/SurfaceCoordinator.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/SurfaceCoordinator.java
new file mode 100644
index 0000000..7e47ea9c
--- /dev/null
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/componentinterfaces/SurfaceCoordinator.java
@@ -0,0 +1,18 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+package org.chromium.chrome.browser.feed.componentinterfaces;
+
+/** Interface for referencing FeedSurfaceCoordinator in this library. */
+public interface SurfaceCoordinator {
+    /** Observes the SurfaceCoordinator. */
+    interface Observer {
+        default void surfaceOpened() {}
+    }
+    void addObserver(Observer observer);
+    void removeObserver(Observer observer);
+
+    void onSurfaceClosed();
+    void onSurfaceOpened();
+    boolean isActive();
+}
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
index 298b5aa1..87b1537 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarController.java
@@ -8,6 +8,7 @@
 
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.feed.FeedServiceBridge;
+import org.chromium.chrome.browser.feed.FeedSurfaceTracker;
 import org.chromium.chrome.browser.feed.v2.FeedUserActionType;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -84,7 +85,7 @@
             if (canRetryFollow(tab, followId, url)) {
                 actionStringId = R.string.web_feed_generic_failure_snackbar_action;
                 if (!isFollowIdValid(followId)) {
-                    snackbarController.pinToUrl(tab);
+                    snackbarController.pinToUrl(tab, url);
                 }
             }
             showSnackbar(mContext.getString(failureMessage), snackbarController,
@@ -110,9 +111,10 @@
             mWebFeedDialogCoordinator.initialize(mContext, mFeedLauncher, title, isActive);
             mWebFeedDialogCoordinator.showDialog();
         } else {
-            SnackbarController snackbarController = new SnackbarController() {
+            SnackbarController snackbarController = new PinnedSnackbarController() {
                 @Override
                 public void onAction(Object actionData) {
+                    super.onAction(actionData);
                     mFeedLauncher.openFollowingFeed();
                 }
             };
@@ -138,9 +140,10 @@
             failureMessage = R.string.web_feed_offline_failure_snackbar_message;
         }
 
-        SnackbarController snackbarController = new SnackbarController() {
+        SnackbarController snackbarController = new PinnedSnackbarController() {
             @Override
             public void onAction(Object actionData) {
+                super.onAction(actionData);
                 FeedServiceBridge.reportOtherUserAction(
                         FeedUserActionType.TAPPED_UNFOLLOW_TRY_AGAIN_ON_SNACKBAR);
                 WebFeedBridge.unfollow(followId, result -> {
@@ -166,36 +169,46 @@
     }
 
     /**
-     * A {@link SnackbarController} for when the snackbar action is to follow. Prefers
-     * {@link WebFeedBridge#followFromId} if an ID is available.
+     * A snackbar controller which dismisses the snackbar if the feed surface is shown, and
+     *  optionally, upon navigation to a different URL.
      */
-    private class FollowActionSnackbarController implements SnackbarController {
-        private final byte[] mFollowId;
-        private final GURL mUrl;
-        private final String mTitle;
-        private final @FeedUserActionType int mUserActionType;
-
-        private Tab mTab;
+    private class PinnedSnackbarController
+            implements SnackbarController, FeedSurfaceTracker.Observer {
+        Tab mPinnedTab;
+        private GURL mPinnedUrl;
         private TabObserver mTabObserver;
 
-        FollowActionSnackbarController(
-                byte[] followId, GURL url, String title, @FeedUserActionType int userActionType) {
-            mFollowId = followId;
-            mUrl = url;
-            mTitle = title;
-            mUserActionType = userActionType;
+        PinnedSnackbarController() {
+            FeedSurfaceTracker.getInstance().addObserver(this);
+        }
+
+        @Override
+        public void onAction(Object actionData) {
+            unregisterObservers();
+        }
+
+        @Override
+        public void onDismissNoAction(Object actionData) {
+            unregisterObservers();
+        }
+
+        @Override
+        public void surfaceOpened() {
+            // Hide the snackbar if the feed surface is opened.
+            mSnackbarManager.dismissSnackbars(this);
         }
 
         /**
          * Watch the current tab. Hide the snackbar if the current tab's URL changes.
          */
-        void pinToUrl(Tab tab) {
+        void pinToUrl(Tab tab, GURL url) {
             assert mTabObserver == null;
-            mTab = tab;
+            mPinnedUrl = url;
+            mPinnedTab = tab;
             mTabObserver = new EmptyTabObserver() {
                 @Override
                 public void onPageLoadStarted(Tab tab, GURL url) {
-                    if (!mUrl.equals(url)) {
+                    if (!mPinnedUrl.equals(url)) {
                         urlChanged();
                     }
                 }
@@ -208,31 +221,56 @@
                     urlChanged();
                 }
             };
-            mTab.addObserver(mTabObserver);
+            mPinnedTab.addObserver(mTabObserver);
         }
 
         private void urlChanged() {
             mSnackbarManager.dismissSnackbars(this);
+        }
+
+        private void unregisterObservers() {
             if (mTabObserver != null) {
-                mTab.removeObserver(mTabObserver);
+                mPinnedTab.removeObserver(mTabObserver);
                 mTabObserver = null;
             }
+            FeedSurfaceTracker.getInstance().removeObserver(this);
+        }
+    }
+
+    /**
+     * A {@link SnackbarController} for when the snackbar action is to follow. Prefers
+     * {@link WebFeedBridge#followFromId} if an ID is available.
+     */
+    private class FollowActionSnackbarController extends PinnedSnackbarController {
+        private final byte[] mFollowId;
+        private final GURL mUrl;
+        private final String mTitle;
+        private final @FeedUserActionType int mUserActionType;
+
+        FollowActionSnackbarController(
+                byte[] followId, GURL url, String title, @FeedUserActionType int userActionType) {
+            mFollowId = followId;
+            mUrl = url;
+            mTitle = title;
+            mUserActionType = userActionType;
         }
 
         @Override
         public void onAction(Object actionData) {
+            super.onAction(actionData);
+
             // The snackbar should not be showing if canRetryFollow() returns false.
-            assert canRetryFollow(mTab, mFollowId, mUrl);
+            assert canRetryFollow(mPinnedTab, mFollowId, mUrl);
             FeedServiceBridge.reportOtherUserAction(mUserActionType);
 
             if (!isFollowIdValid(mFollowId)) {
-                WebFeedBridge.followFromUrl(mTab, mUrl, result -> {
+                WebFeedBridge.followFromUrl(mPinnedTab, mUrl, result -> {
                     byte[] mFollowId = result.metadata != null ? result.metadata.id : null;
-                    showPostFollowHelp(mTab, result, mFollowId, mUrl, mTitle);
+                    showPostFollowHelp(mPinnedTab, result, mFollowId, mUrl, mTitle);
                 });
             } else {
                 WebFeedBridge.followFromId(mFollowId,
-                        result -> showPostFollowHelp(mTab, result, mFollowId, mUrl, mTitle));
+                        result -> showPostFollowHelp(mPinnedTab, result, mFollowId, mUrl, mTitle));
             }
         }
     }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
index df153e1..a8bb6f2 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/webfeed/WebFeedSnackbarControllerTest.java
@@ -41,6 +41,7 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.feed.FeedServiceBridge;
+import org.chromium.chrome.browser.feed.FeedSurfaceTracker;
 import org.chromium.chrome.browser.feed.v2.FeedUserActionType;
 import org.chromium.chrome.browser.feed.webfeed.WebFeedSnackbarController.FeedLauncher;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -402,6 +403,17 @@
                 WebFeedSnackbarController.SNACKBAR_DURATION_MS, snackbar.getDuration());
     }
 
+    @Test
+    public void postFollowSnackbarIsDismissedUponFeedSurfaceOpened() {
+        mWebFeedSnackbarController.showPostFollowHelp(
+                mTab, getSuccessfulFollowResult(), sFollowId, sTestUrl, sTitle);
+        verify(mSnackbarManager).showSnackbar(mSnackbarCaptor.capture());
+        Snackbar snackbar = mSnackbarCaptor.getValue();
+
+        FeedSurfaceTracker.getInstance().surfaceOpened();
+        verify(mSnackbarManager).dismissSnackbars(eq(mSnackbarCaptor.getValue().getController()));
+    }
+
     private WebFeedBridge.FollowResults getSuccessfulFollowResult() {
         return new WebFeedBridge.FollowResults(WebFeedSubscriptionRequestStatus.SUCCESS,
                 new WebFeedBridge.WebFeedMetadata(sFollowId, sTitle, sTestUrl,
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index dd4c5d3..5209c5b 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1749,8 +1749,8 @@
   },
   {
     "name": "enable-de-jelly",
-    "owners": [ "ericrk", "//components/viz/OWNERS" ],
-    "expiry_milestone": 94
+    "owners": [ "boliu", "//components/viz/OWNERS" ],
+    "expiry_milestone": 104
   },
   {
     "name": "enable-debug-for-secure-payment-confirmation",
@@ -3254,6 +3254,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "force-major-version-to-100",
+    "owners": [ "abeyad", "potassium-katabolism@google.com" ],
+    "expiry_milestone": 100
+  },
+  {
     "name": "force-show-update-menu-badge",
     "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/omaha/OWNERS" ],
     // This is required by test teams to verify functionality on devices which
@@ -4369,11 +4374,6 @@
     "expiry_milestone": 96
   },
   {
-    "name": "omnibox-webui-omnibox-popup",
-    "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 99
-  },
-  {
     "name": "optimization-guide-model-downloading",
     "owners": [ "mcrouse", "chrome-intelligence-core@google.com" ],
     "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 7a680477..e0a1c0d2 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2869,6 +2869,13 @@
     "Whether the sharing options in various context menus are grouped into "
     "a common submenu.";
 
+const char kForceMajorVersion100InUserAgentName[] =
+    "Force major version to 100 in User-Agent";
+const char kForceMajorVersion100InUserAgentDescription[] =
+    "Force the Chrome major version in the User-Agent string to 100, which "
+    "allows testing the 3-digit major version number before the actual M100 "
+    "release. This flag is only available from M96-M99.";
+
 // Android ---------------------------------------------------------------------
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 5bf379f..8a60a59f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1634,6 +1634,9 @@
 extern const char kShareContextMenuName[];
 extern const char kShareContextMenuDescription[];
 
+extern const char kForceMajorVersion100InUserAgentName[];
+extern const char kForceMajorVersion100InUserAgentDescription[];
+
 // Android --------------------------------------------------------------------
 
 #if defined(OS_ANDROID)
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 044fefc..346b7e6 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -748,7 +748,7 @@
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kThemeRefactorAndroid{"ThemeRefactorAndroid",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kToolbarIphAndroid{"ToolbarIphAndroid",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListInstrumentationTest.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListInstrumentationTest.java
index 20abfafd..7d4ecf73 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListInstrumentationTest.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureListInstrumentationTest.java
@@ -34,7 +34,6 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Batch(Batch.PER_CLASS)
-@Batch.SplitByFeature
 public class ChromeFeatureListInstrumentationTest {
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
diff --git a/chrome/browser/media/cdm_document_service_impl.cc b/chrome/browser/media/cdm_document_service_impl.cc
index b526685f..d145b44 100644
--- a/chrome/browser/media/cdm_document_service_impl.cc
+++ b/chrome/browser/media/cdm_document_service_impl.cc
@@ -391,6 +391,7 @@
     if (origin_id_string.empty())
       continue;
 
+    DVLOG(2) << __func__ << ": Processing: " << file_path;
     absl::optional<url::Origin> origin = absl::nullopt;
     if (origin_id_mapping.count(origin_id_string) != 0)
       origin = origin_id_mapping.at(origin_id_string);
@@ -417,6 +418,7 @@
     for (auto cdm_data_file_path = file_enumerator.Next();
          !cdm_data_file_path.value().empty();
          cdm_data_file_path = file_enumerator.Next()) {
+      DVLOG(2) << __func__ << ": - Processing: " << cdm_data_file_path;
       base::File::Info file_info;
       if (!base::GetFileInfo(cdm_data_file_path, &file_info)) {
         DVLOG(ERROR) << "Failed to get FileInfo";
@@ -424,8 +426,9 @@
         break;
       }
 
-      if (file_info.last_accessed >= start &&
-          (!end.is_null() || file_info.last_accessed <= end)) {
+      if (file_info.last_modified >= start &&
+          (end.is_null() || file_info.last_modified <= end)) {
+        DVLOG(2) << "Deleting file. Last modified: " << file_info.last_modified;
         should_delete = true;
         break;
       }
diff --git a/chrome/browser/media/cdm_document_service_impl_test.cc b/chrome/browser/media/cdm_document_service_impl_test.cc
index a76925c1..dac34c1c 100644
--- a/chrome/browser/media/cdm_document_service_impl_test.cc
+++ b/chrome/browser/media/cdm_document_service_impl_test.cc
@@ -6,7 +6,10 @@
 
 #include <memory>
 
+#include "base/files/file.h"
+#include "base/files/file_util.h"
 #include "base/json/values_util.h"
+#include "base/logging.h"
 #include "base/run_loop.h"
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
@@ -33,6 +36,17 @@
 namespace {
 // copied from cdm_pref_service_helper.cc for testing
 const char kOriginId[] = "origin_id";
+
+base::FilePath CreateDummyCdmDataFile(const base::FilePath& cdm_store_path_root,
+                                      const base::UnguessableToken& origin_id) {
+  // Create a fake CDM file
+  auto cdm_store_path = cdm_store_path_root.AppendASCII(origin_id.ToString());
+  base::CreateDirectory(cdm_store_path);
+  auto cdm_data_file_path = cdm_store_path.AppendASCII("cdm_data_file.txt");
+  base::File file(cdm_data_file_path,
+                  base::File::FLAG_CREATE | base::File::FLAG_WRITE);
+  return cdm_data_file_path;
+}
 }  // namespace
 
 namespace content {
@@ -211,7 +225,11 @@
   const auto kOrigin = url::Origin::Create(GURL(kTestOrigin));
 
   NavigateToUrlAndCreateCdmDocumentService(GURL(kTestOrigin));
-  base::UnguessableToken origin_id = GetMediaFoundationCdmData()->origin_id;
+  auto cdm_data = GetMediaFoundationCdmData();
+  base::UnguessableToken origin_id = cdm_data->origin_id;
+
+  base::FilePath cdm_data_file_path = CreateDummyCdmDataFile(
+      cdm_data->cdm_store_path_root, cdm_data->origin_id);
 
   base::Time start = base::Time::Now() - base::TimeDelta::FromHours(1);
   base::Time end;  // null time
@@ -228,6 +246,7 @@
   base::UnguessableToken same_origin_id =
       GetMediaFoundationCdmData()->origin_id;
   ASSERT_EQ(origin_id, same_origin_id);
+  ASSERT_TRUE(base::PathExists(cdm_data_file_path));
 
   base::RunLoop loop2;
 
@@ -240,6 +259,7 @@
 
   base::UnguessableToken new_origin_id = GetMediaFoundationCdmData()->origin_id;
   ASSERT_NE(origin_id, new_origin_id);
+  ASSERT_FALSE(base::PathExists(cdm_data_file_path));
 }
 
 // Check that we only clear the CDM preference that were set between start and
@@ -248,7 +268,10 @@
   const auto kOrigin = url::Origin::Create(GURL(kTestOrigin));
 
   NavigateToUrlAndCreateCdmDocumentService(GURL(kTestOrigin));
-  base::UnguessableToken origin_id = GetMediaFoundationCdmData()->origin_id;
+  auto cdm_data = GetMediaFoundationCdmData();
+  base::UnguessableToken origin_id = cdm_data->origin_id;
+  base::FilePath cdm_data_file_path =
+      CreateDummyCdmDataFile(cdm_data->cdm_store_path_root, origin_id);
 
   base::Time start = base::Time::Now() - base::TimeDelta::FromHours(4);
   base::Time end = start - base::TimeDelta::FromHours(2);
@@ -264,6 +287,7 @@
 
   base::UnguessableToken new_origin_id = GetMediaFoundationCdmData()->origin_id;
   ASSERT_EQ(origin_id, new_origin_id);
+  ASSERT_TRUE(base::PathExists(cdm_data_file_path));
 }
 
 TEST_F(CdmDocumentServiceImplTest, ClearCdmPreferenceDataNullFilter) {
diff --git a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc b/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
index a2ac1ba..a4ba482 100644
--- a/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
+++ b/chrome/browser/media/webrtc/conditional_focus_browsertest.cc
@@ -234,7 +234,7 @@
 
   // Test.
   CallFocusAndExpectError(
-      "NotSupportedError: Failed to execute 'focus' on "
+      "InvalidStateError: Failed to execute 'focus' on "
       "'FocusableMediaStreamTrack': Method may only be called once.");
 }
 
diff --git a/chrome/browser/metrics/chrome_metrics_service_accessor.h b/chrome/browser/metrics/chrome_metrics_service_accessor.h
index 0aafc68..4da4c523 100644
--- a/chrome/browser/metrics/chrome_metrics_service_accessor.h
+++ b/chrome/browser/metrics/chrome_metrics_service_accessor.h
@@ -33,6 +33,10 @@
 class ChromeCameraAppUIDelegate;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
+namespace autofill_assistant {
+class ClientAndroid;
+}  // namespace autofill_assistant
+
 namespace domain_reliability {
 class DomainReliabilityServiceFactory;
 }
@@ -98,6 +102,7 @@
   static void SetMetricsAndCrashReportingForTesting(const bool* value);
 
  private:
+  friend class autofill_assistant::ClientAndroid;
   friend class ::CrashesDOMHandler;
   friend class ::FlashDOMHandler;
   friend class ChromeBrowserFieldTrials;
diff --git a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
index 7e411af..70c722c3 100644
--- a/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
+++ b/chrome/browser/metrics/usertype_by_devicetype_metrics_provider_browsertest.cc
@@ -406,7 +406,7 @@
 #else
 #define MAYBE_Uma Uma
 #endif
-IN_PROC_BROWSER_TEST_P(UserTypeByDeviceTypeMetricsProviderTest, Uma) {
+IN_PROC_BROWSER_TEST_P(UserTypeByDeviceTypeMetricsProviderTest, MAYBE_Uma) {
   base::HistogramTester histogram_tester;
 
   SetDevicePolicy();
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 1e69585d..5180682c 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -276,6 +276,7 @@
 #include "chrome/browser/ash/app_mode/kiosk_app_manager.h"
 #include "chrome/browser/ash/app_mode/kiosk_cryptohome_remover.h"
 #include "chrome/browser/ash/app_mode/web_app/web_kiosk_app_manager.h"
+#include "chrome/browser/ash/app_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/apps/apk_web_app_service.h"
 #include "chrome/browser/ash/arc/policy/arc_policy_bridge.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
@@ -295,7 +296,6 @@
 #include "chrome/browser/ash/customization/customization_document.h"
 #include "chrome/browser/ash/file_system_provider/registry.h"
 #include "chrome/browser/ash/first_run/first_run.h"
-#include "chrome/browser/ash/full_restore/full_restore_prefs.h"
 #include "chrome/browser/ash/guest_os/guest_os_mime_types_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_pref_names.h"
 #include "chrome/browser/ash/lock_screen_apps/state_controller.h"
diff --git a/chrome/browser/resources/history/BUILD.gn b/chrome/browser/resources/history/BUILD.gn
index df83c91..ea62ad5d3 100644
--- a/chrome/browser/resources/history/BUILD.gn
+++ b/chrome/browser/resources/history/BUILD.gn
@@ -71,6 +71,7 @@
     "constants.ts",
     "externs.ts",
     "history_clusters/browser_proxy.ts",
+    "history_clusters/open_window_proxy.ts",
     "history.ts",
     "lazy_load.ts",
     "query_manager.ts",
@@ -156,6 +157,7 @@
     "history_clusters/cluster.ts",
     "history_clusters/clusters.ts",
     "history_clusters/history_clusters.mojom-webui.js",
+    "history_clusters/open_window_proxy.ts",
     "history_clusters/page_favicon.ts",
     "history_clusters/search_query.ts",
     "history_clusters/shared_style.ts",
diff --git a/chrome/browser/resources/history/history_clusters/open_window_proxy.ts b/chrome/browser/resources/history/history_clusters/open_window_proxy.ts
new file mode 100644
index 0000000..0bc84f4
--- /dev/null
+++ b/chrome/browser/resources/history/history_clusters/open_window_proxy.ts
@@ -0,0 +1,26 @@
+// 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.
+
+/**
+ * @fileoverview This file provides an abstraction layer for Window.open() for
+ * for mocking in tests.
+ * TODO(http://crbug.com/1250487): Refactor this file and similar files into
+ * ui/webui/resources/js/
+ */
+
+export class OpenWindowProxy {
+  open(url: string) {
+    window.open(url);
+  }
+
+  static getInstance(): OpenWindowProxy {
+    return instance || (instance = new OpenWindowProxy());
+  }
+
+  static setInstance(obj: OpenWindowProxy) {
+    instance = obj;
+  }
+}
+
+let instance: OpenWindowProxy|null = null;
diff --git a/chrome/browser/resources/history/history_clusters/search_query.html b/chrome/browser/resources/history/history_clusters/search_query.html
index 095d22ad..8e4e7a0 100644
--- a/chrome/browser/resources/history/history_clusters/search_query.html
+++ b/chrome/browser/resources/history/history_clusters/search_query.html
@@ -31,7 +31,8 @@
     margin-inline-start: 8px;
   }
 </style>
-<a class="pill pill-icon-start" href$="[[searchQuery.url.url]]">
+<a class="pill pill-icon-start" href$="[[searchQuery.url.url]]"
+    on-click="onClick_">
   <div id="icon"></div>
   <div id="text" class="truncate">[[searchQuery.query]]</div>
 </a>
diff --git a/chrome/browser/resources/history/history_clusters/search_query.ts b/chrome/browser/resources/history/history_clusters/search_query.ts
index 459189da..885018d 100644
--- a/chrome/browser/resources/history/history_clusters/search_query.ts
+++ b/chrome/browser/resources/history/history_clusters/search_query.ts
@@ -7,6 +7,7 @@
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {SearchQuery} from './history_clusters.mojom-webui.js';
+import {OpenWindowProxy} from './open_window_proxy.js';
 
 /**
  * @fileoverview This file provides a custom element displaying a search query.
@@ -41,6 +42,15 @@
   //============================================================================
 
   searchQuery: SearchQuery = new SearchQuery();
+
+  //============================================================================
+  // Event handlers
+  //============================================================================
+
+  private onClick_(event: MouseEvent) {
+    event.preventDefault();  // Prevent default browser action (navigation).
+    OpenWindowProxy.getInstance().open(this.searchQuery.url.url);
+  }
 }
 
 customElements.define(SearchQueryElement.is, SearchQueryElement);
diff --git a/chrome/browser/resources/history/history_clusters/url_visit.html b/chrome/browser/resources/history/history_clusters/url_visit.html
index 9f07a97..7b39e541e 100644
--- a/chrome/browser/resources/history/history_clusters/url_visit.html
+++ b/chrome/browser/resources/history/history_clusters/url_visit.html
@@ -1,6 +1,5 @@
 <style include="history-clusters-shared-style">
   :host {
-    cursor: pointer;
     display: flex;
     height: 64px;
   }
@@ -23,12 +22,15 @@
     box-shadow: inset 0 0 0 2px var(--cr-focus-outline-color);
   }
 
+  a {
+    color: inherit;
+    text-decoration: none;
+  }
+
   #start-justified {
     align-items: center;
-    color: inherit;
     display: flex;
     min-width: 0;
-    text-decoration: none;
   }
 
   #page-info {
@@ -99,8 +101,8 @@
     --cr-icon-button-margin-end: 1px;
   }
 </style>
-<div id="header" tabindex="0">
-  <a id="start-justified" href="[[visit.normalizedUrl.url]]" tabindex="-1">
+<a id="header" href="[[visit.normalizedUrl.url]]" on-click="onClick_">
+  <div id="start-justified">
     <page-favicon is-top-visit-favicon="[[isTopVisit]]"
         url="[[visit.normalizedUrl]]">
     </page-favicon>
@@ -117,14 +119,14 @@
         <span id="debug-info" hidden="[[!debugInfo_]]">[[debugInfo_]]</span>
       </span>
     </div>
-  </a>
+  </div>
   <div id="end-justified">
     <div id="timestamp" hidden="[[!isTopVisit]]">[[visit.relativeDate]]</div>
     <cr-icon-button id="actionMenuButton" class="icon-more-vert"
         on-click="onActionMenuButtonClick_">
     </cr-icon-button>
   </div>
-</div>
+</a>
 
 <cr-lazy-render id="actionMenu">
   <template>
diff --git a/chrome/browser/resources/history/history_clusters/url_visit.ts b/chrome/browser/resources/history/history_clusters/url_visit.ts
index 1f142aa..1215701 100644
--- a/chrome/browser/resources/history/history_clusters/url_visit.ts
+++ b/chrome/browser/resources/history/history_clusters/url_visit.ts
@@ -14,6 +14,7 @@
 import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Annotation, URLVisit} from './history_clusters.mojom-webui.js';
+import {OpenWindowProxy} from './open_window_proxy.js';
 
 /**
  * @fileoverview This file provides a custom element displaying a visit to a
@@ -108,22 +109,22 @@
   //============================================================================
 
   private onActionMenuButtonClick_(event: MouseEvent) {
-    // Only handle main (usually the left) and auxiliary (usually the wheel or
-    // the middle) button presses.
-    if (event.button > 1) {
-      return;
-    }
-
     this.$.actionMenu.get().showAt(this.$.actionMenuButton);
+    event.preventDefault();  // Prevent default browser action (navigation).
   }
 
-  private onRemoveAllButtonClick_(event: MouseEvent) {
-    // Only handle main (usually the left) and auxiliary (usually the wheel or
-    // the middle) button presses.
-    if (event.button > 1) {
+  private onClick_(event: MouseEvent) {
+    // Ignore previousely handled events.
+    if (event.defaultPrevented) {
       return;
     }
 
+    event.preventDefault();  // Prevent default browser action (navigation).
+
+    OpenWindowProxy.getInstance().open(this.visit.normalizedUrl.url);
+  }
+
+  private onRemoveAllButtonClick_() {
     this.dispatchEvent(new CustomEvent('remove-visits', {
       bubbles: true,
       composed: true,
@@ -133,13 +134,7 @@
     this.$.actionMenu.get().close();
   }
 
-  private onRemoveSelfButtonClick_(event: MouseEvent) {
-    // Only handle main (usually the left) and auxiliary (usually the wheel or
-    // the middle) button presses.
-    if (event.button > 1) {
-      return;
-    }
-
+  private onRemoveSelfButtonClick_() {
     this.dispatchEvent(new CustomEvent('remove-visits', {
       bubbles: true,
       composed: true,
@@ -189,7 +184,7 @@
    * Returns the domain name of `url` without the leading 'www.'.
    */
   private getHostnameFromUrl_(url: Url): string {
-    return new URL(url.url).hostname.replace(/^(www\.)/, '');
+    return new URL(url.url).hostname.replace(/^(www\.)/, '').trim();
   }
 }
 
diff --git a/chrome/browser/resources/preinstalled_web_apps/resources.grd b/chrome/browser/resources/preinstalled_web_apps/resources.grd
index 88f638e7..c9560bfc 100644
--- a/chrome/browser/resources/preinstalled_web_apps/resources.grd
+++ b/chrome/browser/resources/preinstalled_web_apps/resources.grd
@@ -18,7 +18,7 @@
       <include name="IDR_PREINSTALLED_WEB_APPS_GOOGLE_SLIDES_ICON_192_PNG" file="internal/google_slides_192.png" type="BINDATA" />
       <include name="IDR_PREINSTALLED_WEB_APPS_GMAIL_ICON_192_PNG" file="internal/gmail_192.png" type="BINDATA" />
       <include name="IDR_PREINSTALLED_WEB_APPS_YOUTUBE_ICON_192_PNG" file="internal/youtube_192.png" type="BINDATA" />
-      <if expr="chromeos">
+      <if expr="chromeos or lacros">
         <include name="IDR_PREINSTALLED_WEB_APPS_CALCULATOR_ICON_256_PNG" file="internal/calculator_256.png" type="BINDATA" />
         <include name="IDR_PREINSTALLED_WEB_APPS_GOOGLE_CALENDAR_ICON_192_PNG" file="internal/google_calendar_192.png" type="BINDATA" />
       </if>
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn
index 6cc78ec6a..116b770 100644
--- a/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -83,8 +83,8 @@
     "data/cloud_parsers.ts",
     "data/coordinate2d.ts",
     "data/destination.ts",
-    "data/destination_match.js",
-    "data/destination_store.js",
+    "data/destination_match.ts",
+    "data/destination_store.ts",
     "data/document_info.ts",
     "data/local_parsers.ts",
     "data/margins.ts",
@@ -104,8 +104,8 @@
 
   if (is_chromeos) {
     in_files += [
-      "data/print_server_store.js",
-      "data/printer_status_cros.js",
+      "data/print_server_store.ts",
+      "data/printer_status_cros.ts",
       "native_layer_cros.js",
     ]
   }
@@ -245,8 +245,8 @@
     "data/cloud_parsers.ts",
     "data/coordinate2d.ts",
     "data/destination.ts",
-    "data/destination_match.js",
-    "data/destination_store.js",
+    "data/destination_match.ts",
+    "data/destination_store.ts",
     "data/document_info.ts",
     "data/local_parsers.ts",
     "data/margins.ts",
@@ -301,8 +301,8 @@
 
   if (is_chromeos) {
     in_files += [
-      "data/print_server_store.js",
-      "data/printer_status_cros.js",
+      "data/print_server_store.ts",
+      "data/printer_status_cros.ts",
       "native_layer_cros.js",
       "ui/destination_dialog_cros.js",
       "ui/destination_dropdown_cros.js",
diff --git a/chrome/browser/resources/print_preview/cloud_print_interface.js b/chrome/browser/resources/print_preview/cloud_print_interface.js
index b4981d4e..1bc7947 100644
--- a/chrome/browser/resources/print_preview/cloud_print_interface.js
+++ b/chrome/browser/resources/print_preview/cloud_print_interface.js
@@ -46,6 +46,7 @@
 
 /**
  * @typedef {{
+ *   account: string,
  *   destinationId: string,
  *   origin: !DestinationOrigin,
  * }}
diff --git a/chrome/browser/resources/print_preview/data/cdd.ts b/chrome/browser/resources/print_preview/data/cdd.ts
index 4cf306b..6aaa3b76 100644
--- a/chrome/browser/resources/print_preview/data/cdd.ts
+++ b/chrome/browser/resources/print_preview/data/cdd.ts
@@ -84,10 +84,11 @@
   reset_to_default?: boolean,
 };
 
-type MediaSizeOption = {
+export type MediaSizeOption = {
   type?: string,
   vendor_id?: string,
   custom_display_name?: string,
+  custom_display_name_localized?: string,
   is_default?: boolean,
   name?: string,
 };
diff --git a/chrome/browser/resources/print_preview/data/destination_match.js b/chrome/browser/resources/print_preview/data/destination_match.js
deleted file mode 100644
index c535bdc7..0000000
--- a/chrome/browser/resources/print_preview/data/destination_match.js
+++ /dev/null
@@ -1,147 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {assert} from 'chrome://resources/js/assert.m.js';
-import {CloudOrigins, Destination, DestinationOrigin, GooglePromotedDestinationId, RecentDestination} from './destination.js';
-
-/**
- * Printer types for capabilities and printer list requests.
- * Must match PrinterType in printing/print_job_constants.h
- * Note: PRIVET_PRINTER is deprecated.
- * @enum {number}
- */
-export const PrinterType = {
-  PRIVET_PRINTER: 0,
-  EXTENSION_PRINTER: 1,
-  PDF_PRINTER: 2,
-  LOCAL_PRINTER: 3,
-  CLOUD_PRINTER: 4
-};
-
-/**
- * Converts DestinationOrigin to PrinterType.
- * @param {!DestinationOrigin} origin The printer's destination origin.
- * return {!PrinterType} The corresponding PrinterType.
- */
-export const originToType = function(origin) {
-  if (origin === DestinationOrigin.LOCAL || origin === DestinationOrigin.CROS) {
-    return PrinterType.LOCAL_PRINTER;
-  }
-  if (origin === DestinationOrigin.EXTENSION) {
-    return PrinterType.EXTENSION_PRINTER;
-  }
-  assert(CloudOrigins.includes(origin));
-  return PrinterType.CLOUD_PRINTER;
-};
-
-/**
- * @param {!Destination|!RecentDestination} destination The destination to
- *     figure out the printer type of.
- * @return {!PrinterType} Map the destination to a PrinterType.
- */
-export function getPrinterTypeForDestination(destination) {
-  // <if expr="chromeos or lacros">
-  if (destination.id === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
-    return PrinterType.PDF_PRINTER;
-  }
-  // </if>
-
-  if (destination.id === GooglePromotedDestinationId.SAVE_AS_PDF) {
-    return PrinterType.PDF_PRINTER;
-  }
-  return originToType(destination.origin);
-}
-
-export class DestinationMatch {
-  /**
-   * A set of key parameters describing a destination used to determine
-   * if two destinations are the same.
-   * @param {!Array<!DestinationOrigin>} origins Match
-   *     destinations from these origins.
-   * @param {RegExp} idRegExp Match destination's id.
-   * @param {RegExp} displayNameRegExp Match destination's displayName.
-   * @param {boolean} skipVirtualDestinations Whether to ignore virtual
-   *     destinations, for example, Save as PDF.
-   */
-  constructor(origins, idRegExp, displayNameRegExp, skipVirtualDestinations) {
-    /** @private {!Array<!DestinationOrigin>} */
-    this.origins_ = origins;
-
-    /** @private {RegExp} */
-    this.idRegExp_ = idRegExp;
-
-    /** @private {RegExp} */
-    this.displayNameRegExp_ = displayNameRegExp;
-
-    /** @private {boolean} */
-    this.skipVirtualDestinations_ = skipVirtualDestinations;
-  }
-
-  /**
-   * @param {!DestinationOrigin} origin Origin to match.
-   * @return {boolean} Whether the origin is one of the {@code origins_}.
-   */
-  matchOrigin(origin) {
-    return this.origins_.includes(origin);
-  }
-
-  /**
-   * @param {string} id Id of the destination.
-   * @param {!DestinationOrigin} origin Origin of the
-   *     destination.
-   * @return {boolean} Whether destination is the same as initial.
-   */
-  matchIdAndOrigin(id, origin) {
-    return this.matchOrigin(origin) && !!this.idRegExp_ &&
-        this.idRegExp_.test(id);
-  }
-
-  /**
-   * @param {!Destination} destination Destination to match.
-   * @return {boolean} Whether {@code destination} matches the last user
-   *     selected one.
-   */
-  match(destination) {
-    if (!this.matchOrigin(destination.origin)) {
-      return false;
-    }
-    if (this.idRegExp_ && !this.idRegExp_.test(destination.id)) {
-      return false;
-    }
-    if (this.displayNameRegExp_ &&
-        !this.displayNameRegExp_.test(destination.displayName)) {
-      return false;
-    }
-    if (this.skipVirtualDestinations_ &&
-        this.isVirtualDestination_(destination)) {
-      return false;
-    }
-    return true;
-  }
-
-  /**
-   * @param {!Destination} destination Destination to check.
-   * @return {boolean} Whether {@code destination} is virtual, in terms of
-   *     destination selection.
-   * @private
-   */
-  isVirtualDestination_(destination) {
-    // <if expr="chromeos or lacros">
-    if (destination.id === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
-      return true;
-    }
-    // </if>
-
-    return destination.id === GooglePromotedDestinationId.DOCS ||
-        destination.id === GooglePromotedDestinationId.SAVE_AS_PDF;
-  }
-
-  /**
-   * @return {!Set<!PrinterType>} The printer types that
-   *     correspond to this destination match.
-   */
-  getTypes() {
-    return new Set(this.origins_.map(originToType));
-  }
-}
diff --git a/chrome/browser/resources/print_preview/data/destination_match.ts b/chrome/browser/resources/print_preview/data/destination_match.ts
new file mode 100644
index 0000000..af2c7938
--- /dev/null
+++ b/chrome/browser/resources/print_preview/data/destination_match.ts
@@ -0,0 +1,121 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {CloudOrigins, Destination, DestinationOrigin, GooglePromotedDestinationId, RecentDestination} from './destination.js';
+
+/**
+ * Printer types for capabilities and printer list requests.
+ * Must match PrinterType in printing/print_job_constants.h
+ * Note: PRIVET_PRINTER is deprecated.
+ */
+export enum PrinterType {
+  PRIVET_PRINTER = 0,
+  EXTENSION_PRINTER = 1,
+  PDF_PRINTER = 2,
+  LOCAL_PRINTER = 3,
+  CLOUD_PRINTER = 4
+}
+
+export function originToType(origin: DestinationOrigin): PrinterType {
+  if (origin === DestinationOrigin.LOCAL || origin === DestinationOrigin.CROS) {
+    return PrinterType.LOCAL_PRINTER;
+  }
+  if (origin === DestinationOrigin.EXTENSION) {
+    return PrinterType.EXTENSION_PRINTER;
+  }
+  assert(CloudOrigins.includes(origin));
+  return PrinterType.CLOUD_PRINTER;
+}
+
+export function getPrinterTypeForDestination(
+    destination: (Destination|RecentDestination)): PrinterType {
+  // <if expr="chromeos or lacros">
+  if (destination.id === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
+    return PrinterType.PDF_PRINTER;
+  }
+  // </if>
+
+  if (destination.id === GooglePromotedDestinationId.SAVE_AS_PDF) {
+    return PrinterType.PDF_PRINTER;
+  }
+  return originToType(destination.origin);
+}
+
+export class DestinationMatch {
+  private origins_: DestinationOrigin[];
+
+  private idRegExp_: RegExp|null;
+
+  private displayNameRegExp_: RegExp|null;
+
+  private skipVirtualDestinations_: boolean;
+
+  /**
+   * A set of key parameters describing a destination used to determine
+   * if two destinations are the same.
+   * @param origins Match destinations from these origins.
+   * @param idRegExp Match destination's id.
+   * @param displayNameRegExp Match destination's displayName.
+   * @param skipVirtualDestinations Whether to ignore virtual
+   *     destinations, for example, Save as PDF.
+   */
+  constructor(
+      origins: DestinationOrigin[], idRegExp: RegExp|null,
+      displayNameRegExp: RegExp|null, skipVirtualDestinations: boolean) {
+    this.origins_ = origins;
+    this.idRegExp_ = idRegExp;
+    this.displayNameRegExp_ = displayNameRegExp;
+    this.skipVirtualDestinations_ = skipVirtualDestinations;
+  }
+
+  matchOrigin(origin: DestinationOrigin): boolean {
+    return this.origins_.includes(origin);
+  }
+
+  matchIdAndOrigin(id: string, origin: DestinationOrigin): boolean {
+    return this.matchOrigin(origin) && !!this.idRegExp_ &&
+        this.idRegExp_.test(id);
+  }
+
+  match(destination: Destination): boolean {
+    if (!this.matchOrigin(destination.origin)) {
+      return false;
+    }
+    if (this.idRegExp_ && !this.idRegExp_.test(destination.id)) {
+      return false;
+    }
+    if (this.displayNameRegExp_ &&
+        !this.displayNameRegExp_.test(destination.displayName)) {
+      return false;
+    }
+    if (this.skipVirtualDestinations_ &&
+        this.isVirtualDestination_(destination)) {
+      return false;
+    }
+    return true;
+  }
+
+  /**
+   * @return Whether {@code destination} is virtual, in terms of
+   *     destination selection.
+   */
+  private isVirtualDestination_(destination: Destination): boolean {
+    // <if expr="chromeos or lacros">
+    if (destination.id === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
+      return true;
+    }
+    // </if>
+
+    return destination.id === GooglePromotedDestinationId.DOCS ||
+        destination.id === GooglePromotedDestinationId.SAVE_AS_PDF;
+  }
+
+  /**
+   * @return The printer types that correspond to this destination match.
+   */
+  getTypes(): Set<PrinterType> {
+    return new Set(this.origins_.map(originToType));
+  }
+}
diff --git a/chrome/browser/resources/print_preview/data/destination_store.js b/chrome/browser/resources/print_preview/data/destination_store.ts
similarity index 70%
rename from chrome/browser/resources/print_preview/data/destination_store.js
rename to chrome/browser/resources/print_preview/data/destination_store.ts
index f793196..83de3eb0 100644
--- a/chrome/browser/resources/print_preview/data/destination_store.js
+++ b/chrome/browser/resources/print_preview/data/destination_store.ts
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.m.js';
-import {isChromeOS, isLacros} from 'chrome://resources/js/cr.m.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
 import {EventTracker} from 'chrome://resources/js/event_tracker.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
@@ -15,7 +14,7 @@
 import {NativeLayerCros, NativeLayerCrosImpl, PrinterSetupResponse} from '../native_layer_cros.js';
 
 // </if>
-import {Cdd} from './cdd.js';
+import {Cdd, MediaSizeOption} from './cdd.js';
 import {CloudOrigins, createDestinationKey, createRecentDestinationKey, Destination, DestinationConnectionStatus, DestinationOrigin, DestinationProvisionalType, DestinationType, GooglePromotedDestinationId, RecentDestination} from './destination.js';
 import {DestinationMatch, getPrinterTypeForDestination, originToType, PrinterType} from './destination_match.js';
 import {LocalDestinationInfo, parseDestination, parseExtensionDestination, ProvisionalDestinationInfo} from './local_parsers.js';
@@ -24,29 +23,27 @@
  * Printer search statuses used by the destination store.
  * @enum {string}
  */
-const DestinationStorePrinterSearchStatus = {
-  START: 'start',
-  SEARCHING: 'searching',
-  DONE: 'done'
-};
+enum DestinationStorePrinterSearchStatus {
+  START = 'start',
+  SEARCHING = 'searching',
+  DONE = 'done'
+}
 
 /**
  * Enumeration of possible destination errors.
- * @enum {number}
  */
-export const DestinationErrorType = {
-  INVALID: 0,
-  UNSUPPORTED: 1,
-  NO_DESTINATIONS: 2,
-};
+export enum DestinationErrorType {
+  INVALID = 0,
+  UNSUPPORTED = 1,
+  NO_DESTINATIONS = 2,
+}
 
 /**
  * Localizes printer capabilities.
- * @param {!Cdd} capabilities Printer capabilities to
- *     localize.
- * @return {!Cdd} Localized capabilities.
+ * @param capabilities Printer capabilities to localize.
+ * @return Localized capabilities.
  */
-const localizeCapabilities = function(capabilities) {
+function localizeCapabilities(capabilities: Cdd): Cdd {
   if (!capabilities.printer) {
     return capabilities;
   }
@@ -60,32 +57,26 @@
     // No need to patch capabilities with localized names provided.
     if (!media.custom_display_name_localized) {
       media.custom_display_name = media.custom_display_name ||
-          DestinationStore.MEDIA_DISPLAY_NAMES_[media.name] || media.name;
+          MEDIA_DISPLAY_NAMES_[media.name!] || media.name;
     }
   }
   return capabilities;
-};
+}
 
 /**
  * Compare two media sizes by their names.
- * @param {!Object} a Media to compare.
- * @param {!Object} b Media to compare.
- * @return {number} 1 if a > b, -1 if a < b, or 0 if a === b.
+ * @return 1 if a > b, -1 if a < b, or 0 if a === b.
  */
-const compareMediaNames = function(a, b) {
-  const nameA = a.custom_display_name_localized || a.custom_display_name;
-  const nameB = b.custom_display_name_localized || b.custom_display_name;
+function compareMediaNames(a: MediaSizeOption, b: MediaSizeOption): number {
+  const nameA = a.custom_display_name_localized || a.custom_display_name || '';
+  const nameB = b.custom_display_name_localized || b.custom_display_name || '';
   return nameA === nameB ? 0 : (nameA > nameB ? 1 : -1);
-};
+}
 
 /**
  * Sort printer media sizes.
- * @param {!Cdd} capabilities Printer capabilities to
- * localize.
- * @return {!Cdd} Localized capabilities.
- * @private
  */
-const sortMediaSizes = function(capabilities) {
+function sortMediaSizes(capabilities: Cdd): Cdd {
   if (!capabilities.printer) {
     return capabilities;
   }
@@ -103,15 +94,15 @@
   // - Japanese
   // - Other metric
   // Otherwise, assume they are custom sizes.
-  const categoryStandardNA = [];
-  const categoryStandardCN = [];
-  const categoryStandardISO = [];
-  const categoryStandardJP = [];
-  const categoryStandardMisc = [];
-  const categoryCustom = [];
+  const categoryStandardNA: MediaSizeOption[] = [];
+  const categoryStandardCN: MediaSizeOption[] = [];
+  const categoryStandardISO: MediaSizeOption[] = [];
+  const categoryStandardJP: MediaSizeOption[] = [];
+  const categoryStandardMisc: MediaSizeOption[] = [];
+  const categoryCustom: MediaSizeOption[] = [];
   for (let i = 0, media; (media = mediaSize.option[i]); i++) {
     const name = media.name || 'CUSTOM';
-    let category;
+    let category: MediaSizeOption[];
     if (name.startsWith('NA_')) {
       category = categoryStandardNA;
     } else if (
@@ -146,56 +137,137 @@
       ...categoryStandardCN, ...categoryStandardISO, ...categoryStandardJP,
       ...categoryStandardMisc, ...categoryCustom);
   return capabilities;
-};
+}
 
+/**
+ * Event types dispatched by the destination store.
+ * @enum {string}
+ */
+export enum DestinationStoreEventType {
+  DESTINATION_SEARCH_DONE = 'DestinationStore.DESTINATION_SEARCH_DONE',
+  DESTINATION_SELECT = 'DestinationStore.DESTINATION_SELECT',
+  DESTINATIONS_INSERTED = 'DestinationStore.DESTINATIONS_INSERTED',
+  ERROR = 'DestinationStore.ERROR',
+  SELECTED_DESTINATION_CAPABILITIES_READY = 'DestinationStore' +
+      '.SELECTED_DESTINATION_CAPABILITIES_READY',
+  // <if expr="chromeos or lacros">
+  DESTINATION_EULA_READY = 'DestinationStore.DESTINATION_EULA_READY',
+  // </if>
+}
 
 export class DestinationStore extends EventTarget {
   /**
+   * Currently active user.
+   */
+  private activeUser_: string = '';
+
+  /**
+   * Whether the destination store will auto select the destination that
+   * matches this set of parameters.
+   */
+  private autoSelectMatchingDestination_: DestinationMatch|null = null;
+
+  /**
+   * Used to fetch cloud-based print destinations.
+   */
+  private cloudPrintInterface_: CloudPrintInterface|null = null;
+
+  /**
+   * Cache used for constant lookup of destinations by key.
+   */
+  private destinationMap_: Map<string, Destination> = new Map();
+
+  /**
+   * Internal backing store for the data store.
+   */
+  private destinations_: Destination[] = [];
+
+  /**
+   * Whether a search for destinations is in progress for each type of
+   * printer.
+   */
+  private destinationSearchStatus_:
+      Map<PrinterType, DestinationStorePrinterSearchStatus>;
+
+  private inFlightCloudPrintRequests_: Set<string> = new Set();
+
+  private initialDestinationSelected_: boolean = false;
+
+  /**
+   * Maps user account to the list of origins for which destinations are
+   * already loaded.
+   */
+  private loadedCloudOrigins_: Map<string, DestinationOrigin[]> = new Map();
+
+  /**
+   * Used to track metrics.
+   */
+  private metrics_: MetricsContext = MetricsContext.destinationSearch();
+
+  /**
+   * Used to fetch local print destinations.
+   */
+  private nativeLayer_: NativeLayer = NativeLayerImpl.getInstance();
+
+  // <if expr="chromeos or lacros">
+  /**
+   * Used to fetch information about Chrome OS local print destinations.
+   */
+  private nativeLayerCros_: NativeLayerCros = NativeLayerCrosImpl.getInstance();
+  // </if>
+
+  /**
+   * Whether PDF printer is enabled. It's disabled, for example, in App
+   * Kiosk mode or when PDF printing is disallowed by policy.
+   */
+  private pdfPrinterEnabled_: boolean = false;
+
+  /**
+   * Local destinations are CROS destinations on ChromeOS because they
+   * require extra setup.
+   */
+  private platformOrigin_: DestinationOrigin;
+
+  private recentDestinationKeys_: string[] = [];
+
+  /**
+   * Currently selected destination.
+   */
+  private selectedDestination_: Destination|null = null;
+
+  /**
+   * Key of the system default destination.
+   */
+  private systemDefaultDestinationKey_: string = '';
+
+  /**
+   * Event tracker used to track event listeners of the destination store.
+   */
+  private tracker_: EventTracker = new EventTracker();
+
+  private typesToSearch_: Set<PrinterType> = new Set();
+
+  /**
+   * Whether to default to the system default printer instead of the most
+   * recent destination.
+   */
+  private useSystemDefaultAsDefault_: boolean;
+
+  /**
    * A data store that stores destinations and dispatches events when the
    * data store changes.
-   * @param {function(string, !Function):void} addListenerCallback Function
-   *     to call to add Web UI listeners in DestinationStore constructor.
+   * @param addListenerCallback Function to call to add Web UI listeners in
+   *     DestinationStore constructor.
    */
-  constructor(addListenerCallback) {
+  constructor(
+      addListenerCallback:
+          (eventName: string,
+           listener:
+               (t: PrinterType,
+                p: LocalDestinationInfo[]|
+                ProvisionalDestinationInfo[]) => void) => void) {
     super();
 
-    /**
-     * Currently active user.
-     * @private {string}
-     */
-    this.activeUser_ = '';
-
-    /**
-     * Whether the destination store will auto select the destination that
-     * matches this set of parameters.
-     * @private {DestinationMatch}
-     */
-    this.autoSelectMatchingDestination_ = null;
-
-    /**
-     * Used to fetch cloud-based print destinations.
-     * @private {CloudPrintInterface}
-     */
-    this.cloudPrintInterface_ = null;
-
-    /**
-     * Cache used for constant lookup of destinations by key.
-     * @private {!Map<string, !Destination>}
-     */
-    this.destinationMap_ = new Map();
-
-    /**
-     * Internal backing store for the data store.
-     * @private {!Array<!Destination>}
-     */
-    this.destinations_ = [];
-
-    /**
-     * Whether a search for destinations is in progress for each type of
-     * printer.
-     * @private {!Map<!PrinterType,
-     *                !DestinationStorePrinterSearchStatus>}
-     */
     this.destinationSearchStatus_ = new Map([
       [
         PrinterType.EXTENSION_PRINTER, DestinationStorePrinterSearchStatus.START
@@ -203,96 +275,27 @@
       [PrinterType.LOCAL_PRINTER, DestinationStorePrinterSearchStatus.START],
     ]);
 
-    /** @private {!Set<string>} */
-    this.inFlightCloudPrintRequests_ = new Set();
-
-    /** @private {boolean} */
-    this.initialDestinationSelected_ = false;
-
-    /**
-     * Maps user account to the list of origins for which destinations are
-     * already loaded.
-     * @private {!Map<string, !Array<!DestinationOrigin>>}
-     */
-    this.loadedCloudOrigins_ = new Map();
-
-    /**
-     * Used to track metrics.
-     * @private {!MetricsContext}
-     */
-    this.metrics_ = MetricsContext.destinationSearch();
-
-    /**
-     * Used to fetch local print destinations.
-     * @private {!NativeLayer}
-     */
-    this.nativeLayer_ = NativeLayerImpl.getInstance();
-
+    this.platformOrigin_ = DestinationOrigin.LOCAL;
     // <if expr="chromeos or lacros">
-    /**
-     * Used to fetch information about Chrome OS local print destinations.
-     * @private {!NativeLayerCros}
-     */
-    this.nativeLayerCros_ = NativeLayerCrosImpl.getInstance();
+    this.platformOrigin_ = DestinationOrigin.CROS;
     // </if>
 
-    /**
-     * Whether PDF printer is enabled. It's disabled, for example, in App
-     * Kiosk mode or when PDF printing is disallowed by policy.
-     * @private {boolean}
-     */
-    this.pdfPrinterEnabled_ = false;
-
-    /**
-     * Local destinations are CROS destinations on ChromeOS because they
-     * require extra setup.
-     * @private {!DestinationOrigin}
-     */
-    this.platformOrigin_ = (isChromeOS || isLacros) ? DestinationOrigin.CROS :
-                                                      DestinationOrigin.LOCAL;
-
-    /** @private {!Array<string>} */
-    this.recentDestinationKeys_ = [];
-
-    /**
-     * Currently selected destination.
-     * @private {Destination}
-     */
-    this.selectedDestination_ = null;
-
-    /**
-     * Key of the system default destination.
-     * @private {string}
-     */
-    this.systemDefaultDestinationKey_ = '';
-
-    /**
-     * Event tracker used to track event listeners of the destination store.
-     * @private {!EventTracker}
-     */
-    this.tracker_ = new EventTracker();
-
-    /** @private {!Set<PrinterType>} */
-    this.typesToSearch_ = new Set();
-
-    /**
-     * Whether to default to the system default printer instead of the most
-     * recent destination.
-     * @private {boolean}
-     */
     this.useSystemDefaultAsDefault_ =
         loadTimeData.getBoolean('useSystemDefaultPrinter');
 
-    addListenerCallback('printers-added', this.onPrintersAdded_.bind(this));
+    addListenerCallback(
+        'printers-added',
+        (type: PrinterType,
+         printers: LocalDestinationInfo[]|ProvisionalDestinationInfo[]) =>
+            this.onPrintersAdded_(type, printers));
   }
 
   /**
-   * @param {?string=} opt_account Account to filter destinations by. When
+   * @param opt_account Account to filter destinations by. When
    *     null or omitted, all destinations are returned.
-   * @return {!Array<!Destination>} List of destinations
-   *     accessible by the {@code account}.
+   * @return List of destinations accessible by the {@code account}.
    */
-  destinations(opt_account) {
+  destinations(opt_account?: string|null): Destination[] {
     return this.destinations_.filter(function(destination) {
       return !destination.account ||
           (!!opt_account && destination.account === opt_account);
@@ -300,9 +303,9 @@
   }
 
   /**
-   * @return {boolean} Whether a search for print destinations is in progress.
+   * @return Whether a search for print destinations is in progress.
    */
-  get isPrintDestinationSearchInProgress() {
+  get isPrintDestinationSearchInProgress(): boolean {
     const isLocalDestinationSearchInProgress =
         Array.from(this.destinationSearchStatus_.values())
             .some(el => el === DestinationStorePrinterSearchStatus.SEARCHING);
@@ -311,25 +314,19 @@
     }
 
     const isCloudDestinationSearchInProgress = !!this.cloudPrintInterface_ &&
-        this.cloudPrintInterface_.isCloudDestinationSearchInProgress();
+        this.cloudPrintInterface_!.isCloudDestinationSearchInProgress();
     return isCloudDestinationSearchInProgress;
   }
 
   /**
-   * @return {Destination} The currently selected destination or
-   *     {@code null} if none is selected.
+   * @return The currently selected destination or null if none is selected.
    */
-  get selectedDestination() {
+  get selectedDestination(): Destination|null {
     return this.selectedDestination_;
   }
 
-  /**
-   * @param {(?Destination |
-   *          ?RecentDestination)} destination
-   * @return {boolean} Whether the destination is valid.
-   * @private
-   */
-  isDestinationValid_(destination) {
+  private isDestinationValid_(destination: (Destination|RecentDestination|
+                                            null)): boolean {
     return !!destination && !!destination.id && !!destination.origin;
   }
 
@@ -337,20 +334,27 @@
    * Initializes the destination store. Sets the initially selected
    * destination. If any inserted destinations match this ID, that destination
    * will be automatically selected.
-   * @param {boolean} pdfPrinterDisabled Whether the PDF print destination is
+   * @param pdfPrinterDisabled Whether the PDF print destination is
    *     disabled in print preview.
-   * @param {boolean} isDriveMounted Whether Google Drive is mounted. Only used
+   * @param isDriveMounted Whether Google Drive is mounted. Only used
         on Chrome OS.
-   * @param {string} systemDefaultDestinationId ID of the system default
+   * @param systemDefaultDestinationId ID of the system default
    *     destination.
-   * @param {?string} serializedDefaultDestinationSelectionRulesStr Serialized
+   * @param serializedDefaultDestinationSelectionRulesStr Serialized
    *     default destination selection rules.
-   * @param {!Array<!RecentDestination>}
-   *     recentDestinations The recent print destinations.
+   * @param recentDestinations The recent print destinations.
    */
   init(
-      pdfPrinterDisabled, isDriveMounted, systemDefaultDestinationId,
-      serializedDefaultDestinationSelectionRulesStr, recentDestinations) {
+      pdfPrinterDisabled: boolean,
+      // <if expr="chromeos or lacros">
+      isDriveMounted: boolean,
+      // </if>
+      // <if expr="not chromeos and not lacros">
+      _isDriveMounted: boolean,
+      // </if>
+      systemDefaultDestinationId: string,
+      serializedDefaultDestinationSelectionRulesStr: string|null,
+      recentDestinations: RecentDestination[]) {
     if (systemDefaultDestinationId) {
       const systemDefaultOrigin =
           this.isDestinationLocal_(systemDefaultDestinationId) ?
@@ -418,11 +422,10 @@
   }
 
   /**
-   * @param {boolean=} timeoutExpired Whether the select timeout is expired.
+   * @param timeoutExpired Whether the select timeout is expired.
    *     Defaults to false.
-   * @private
    */
-  tryToSelectInitialDestination_(timeoutExpired = false) {
+  private tryToSelectInitialDestination_(timeoutExpired: boolean = false) {
     if (this.initialDestinationSelected_) {
       return;
     }
@@ -432,7 +435,7 @@
         this.typesToSearch_.size === 0) {
       // No destinations
       this.dispatchEvent(new CustomEvent(
-          DestinationStore.EventType.ERROR,
+          DestinationStoreEventType.ERROR,
           {detail: DestinationErrorType.NO_DESTINATIONS}));
     }
     this.initialDestinationSelected_ = success;
@@ -450,11 +453,10 @@
    * Called when destinations are added to the store when the initial
    * destination has not yet been set. Selects the initial destination based on
    * relevant policies, recent printers, and system default.
-   * @param {boolean} timeoutExpired Whether the initial timeout has expired.
-   * @return {boolean} Whether an initial destination was successfully selected.
-   * @private
+   * @param timeoutExpired Whether the initial timeout has expired.
+   * @return Whether an initial destination was successfully selected.
    */
-  selectInitialDestination_(timeoutExpired) {
+  private selectInitialDestination_(timeoutExpired: boolean): boolean {
     const searchInProgress = this.typesToSearch_.size !== 0 && !timeoutExpired;
 
     // System default printer policy takes priority.
@@ -517,11 +519,10 @@
   }
 
   /**
-   * @param {string} key The destination key to try to select.
-   * @return {boolean} Whether the destination was found and selected.
-   * @private
+   * @param key The destination key to try to select.
+   * @return Whether the destination was found and selected.
    */
-  tryToSelectDestinationByKey_(key) {
+  private tryToSelectDestinationByKey_(key: string): boolean {
     const candidate = this.destinationMap_.get(key);
     if (candidate) {
       this.selectDestination(candidate);
@@ -530,11 +531,7 @@
     return false;
   }
 
-  /**
-   * @param {?string} destinationId
-   * @return {boolean}
-   */
-  isDestinationLocal_(destinationId) {
+  private isDestinationLocal_(destinationId: string|null): boolean {
     // <if expr="chromeos or lacros">
     if (destinationId === GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS) {
       return true;
@@ -552,16 +549,15 @@
   // <if expr="chromeos or lacros">
   /**
    * Attempts to find the EULA URL of the the destination ID.
-   * @param {string} destinationId ID of the destination.
    */
-  fetchEulaUrl(destinationId) {
+  fetchEulaUrl(destinationId: string) {
     this.nativeLayerCros_.getEulaUrl(destinationId).then(response => {
       // Check that the currently selected destination ID still matches the
       // destination ID we used to fetch the EULA URL.
       if (this.selectedDestination_ &&
           destinationId === this.selectedDestination_.id) {
         this.dispatchEvent(new CustomEvent(
-            DestinationStore.EventType.DESTINATION_EULA_READY,
+            DestinationStoreEventType.DESTINATION_EULA_READY,
             {detail: response}));
       }
     });
@@ -569,21 +565,18 @@
 
   /**
    * Reloads all local printers.
-   * @return {!Promise}
    */
-  reloadLocalPrinters() {
+  reloadLocalPrinters(): Promise<void> {
     return this.nativeLayer_.getPrinters(PrinterType.LOCAL_PRINTER);
   }
   // </if>
 
   /**
-   * @param {?string} serializedDefaultDestinationSelectionRulesStr Serialized
-   *     default destination selection rules.
-   * @return {?DestinationMatch} Creates rules matching
-   *     previously selected destination.
-   * @private
+   * @return Creates rules matching previously selected destination.
    */
-  convertToDestinationMatch_(serializedDefaultDestinationSelectionRulesStr) {
+  private convertToDestinationMatch_(
+      serializedDefaultDestinationSelectionRulesStr: (string|null)):
+      (DestinationMatch|null) {
     let matchRules = null;
     try {
       if (serializedDefaultDestinationSelectionRulesStr) {
@@ -637,53 +630,53 @@
 
   /**
    * Updates the current active user account.
-   * @param {string} activeUser
    */
-  setActiveUser(activeUser) {
+  setActiveUser(activeUser: string) {
     this.activeUser_ = activeUser;
   }
 
   /**
    * Sets the destination store's Google Cloud Print interface.
-   * @param {!CloudPrintInterface} cloudPrintInterface Interface
-   *     to set.
    */
-  setCloudPrintInterface(cloudPrintInterface) {
+  setCloudPrintInterface(cloudPrintInterface: CloudPrintInterface) {
     assert(this.cloudPrintInterface_ === null);
     this.cloudPrintInterface_ = cloudPrintInterface;
     [CloudPrintInterfaceEventType.SEARCH_DONE,
      CloudPrintInterfaceEventType.SEARCH_FAILED,
     ].forEach(eventName => {
       this.tracker_.add(
-          this.cloudPrintInterface_.getEventTarget(), eventName,
-          this.onCloudPrintSearchDone_.bind(this));
+          this.cloudPrintInterface_!.getEventTarget(), eventName,
+          (event: CustomEvent<CloudPrintInterfaceSearchDoneDetail>) =>
+              this.onCloudPrintSearchDone_(event));
     });
     this.tracker_.add(
-        this.cloudPrintInterface_.getEventTarget(),
+        this.cloudPrintInterface_!.getEventTarget(),
         CloudPrintInterfaceEventType.PRINTER_DONE,
-        this.onCloudPrintPrinterDone_.bind(this));
+        (event: CustomEvent<Destination>) =>
+            this.onCloudPrintPrinterDone_(event));
     this.tracker_.add(
-        this.cloudPrintInterface_.getEventTarget(),
+        this.cloudPrintInterface_!.getEventTarget(),
         CloudPrintInterfaceEventType.PRINTER_FAILED,
-        this.onCloudPrintPrinterFailed_.bind(this));
+        (event: CustomEvent<CloudPrintInterfacePrinterFailedDetail>) =>
+            this.onCloudPrintPrinterFailed_(event));
   }
 
-  /** @param {string} key Key identifying the destination to select */
-  selectDestinationByKey(key) {
+  /** @param Key identifying the destination to select */
+  selectDestinationByKey(key: string) {
     assert(this.tryToSelectDestinationByKey_(key));
   }
 
   /**
-   * @param {Destination} destination Destination to select.
+   * @param Destination to select.
    */
-  selectDestination(destination) {
+  selectDestination(destination: Destination) {
     if (destination === this.selectedDestination_) {
       return;
     }
     if (destination === null) {
       this.selectedDestination_ = null;
       this.dispatchEvent(
-          new CustomEvent(DestinationStore.EventType.DESTINATION_SELECT));
+          new CustomEvent(DestinationStoreEventType.DESTINATION_SELECT));
       return;
     }
 
@@ -703,7 +696,7 @@
     }
     // Notify about selected destination change.
     this.dispatchEvent(
-        new CustomEvent(DestinationStore.EventType.DESTINATION_SELECT));
+        new CustomEvent(DestinationStoreEventType.DESTINATION_SELECT));
     // Request destination capabilities from backend, since they are not
     // known yet.
     if (destination.capabilities === null) {
@@ -721,7 +714,7 @@
         assert(
             this.cloudPrintInterface_ !== null,
             'Cloud destination selected, but GCP is not enabled');
-        this.cloudPrintInterface_.printer(
+        this.cloudPrintInterface_!.printer(
             destination.id, destination.origin, destination.account);
       }
     } else {
@@ -732,22 +725,19 @@
   // <if expr="chromeos or lacros">
   /**
    * Attempt to resolve the capabilities for a Chrome OS printer.
-   * @param {!Destination} destination The destination which
-   *     requires resolution.
-   * @return {!Promise<!PrinterSetupResponse>}
    */
-  resolveCrosDestination(destination) {
+  resolveCrosDestination(destination: Destination):
+      Promise<PrinterSetupResponse> {
     assert(destination.origin === DestinationOrigin.CROS);
     return this.nativeLayerCros_.setupPrinter(destination.id);
   }
 
   /**
    * Attempts to resolve a provisional destination.
-   * @param {!Destination} destination Provisional destination
-   *     that should be resolved.
-   * @return {!Promise<?Destination>}
+   * @param Provisional destination that should be resolved.
    */
-  resolveProvisionalDestination(destination) {
+  resolveProvisionalDestination(destination: Destination):
+      Promise<Destination|null> {
     assert(
         destination.provisionalType ===
             DestinationProvisionalType.NEEDS_USB_PERMISSION,
@@ -780,15 +770,14 @@
   /**
    * Selects the Save as PDF fallback if it is available. If not, selects the
    * first destination if it exists.
-   * @return {boolean} Whether a final destination could be found.
-   * @private
+   * @return Whether a final destination could be found.
    */
-  selectFinalFallbackDestination_() {
+  private selectFinalFallbackDestination_(): boolean {
     // Save as PDF should always exist if it is enabled.
     if (this.pdfPrinterEnabled_) {
       const saveToPdfKey = createDestinationKey(
           GooglePromotedDestinationId.SAVE_AS_PDF, DestinationOrigin.LOCAL, '');
-      this.selectDestination(assert(this.destinationMap_.get(saveToPdfKey)));
+      this.selectDestination(assert(this.destinationMap_.get(saveToPdfKey)!));
       return true;
     }
 
@@ -806,11 +795,9 @@
 
   /**
    * Initiates loading of destinations.
-   * @param {!PrinterType} type The type of destinations to
-   *     load.
-   * @private
+   * @param type The type of destinations to load.
    */
-  startLoadDestinations_(type) {
+  private startLoadDestinations_(type: PrinterType) {
     if (this.destinationSearchStatus_.get(type) ===
         DestinationStorePrinterSearchStatus.DONE) {
       return;
@@ -818,20 +805,19 @@
     this.destinationSearchStatus_.set(
         type, DestinationStorePrinterSearchStatus.SEARCHING);
     this.nativeLayer_.getPrinters(type).then(
-        this.onDestinationSearchDone_.bind(this, type));
+        () => this.onDestinationSearchDone_(type));
     MetricsContext.getPrinters(type).record(
         Metrics.PrintPreviewInitializationEvents.FUNCTION_INITIATED);
   }
 
   /**
    * Requests load of COOKIE based cloud destinations for |account|.
-   * @param {string} account
    */
-  reloadUserCookieBasedDestinations(account) {
+  reloadUserCookieBasedDestinations(account: string) {
     const origins = this.loadedCloudOrigins_.get(account) || [];
     if (origins.includes(DestinationOrigin.COOKIES)) {
       this.dispatchEvent(
-          new CustomEvent(DestinationStore.EventType.DESTINATION_SEARCH_DONE));
+          new CustomEvent(DestinationStoreEventType.DESTINATION_SEARCH_DONE));
     } else {
       this.startLoadCloudDestinations(DestinationOrigin.COOKIES);
     }
@@ -856,10 +842,9 @@
 
   /**
    * Initiates loading of cloud destinations.
-   * @param {DestinationOrigin=} opt_origin Search destinations
-   *     for the specified origin only.
+   * @param opt_origin Search destinations for the specified origin only.
    */
-  startLoadCloudDestinations(opt_origin) {
+  startLoadCloudDestinations(opt_origin?: DestinationOrigin) {
     if (this.cloudPrintInterface_ === null) {
       return;
     }
@@ -871,10 +856,9 @@
   }
 
   /**
-   * @param {string} key Key identifying the destination
-   * @return {?Destination} The destination matching the key, if it exists.
+   * @return The destination matching the key, if it exists.
    */
-  getDestinationByKey(key) {
+  getDestinationByKey(key: string): Destination|undefined {
     return this.destinationMap_.get(key);
   }
 
@@ -882,51 +866,37 @@
   /**
    * Removes the provisional destination with ID |provisionalId| from
    * |destinationMap_| and |destinations_|.
-   * @param{string} provisionalId The provisional destination ID.
-   * @private
    */
-  removeProvisionalDestination_(provisionalId) {
-    this.destinations_ = this.destinations_.filter(function(el) {
+  private removeProvisionalDestination_(provisionalId: string) {
+    this.destinations_ = this.destinations_.filter(el => {
       if (el.id === provisionalId) {
         this.destinationMap_.delete(el.key);
         return false;
       }
       return true;
-    }, this);
+    });
   }
   // </if>
 
   /**
    * Inserts {@code destination} to the data store and dispatches a
    * DESTINATIONS_INSERTED event.
-   * @param {!Destination} destination Print destination to
-   *     insert.
-   * @private
    */
-  insertDestination_(destination) {
+  private insertDestination_(destination: Destination) {
     if (this.insertIntoStore_(destination)) {
-      this.destinationsInserted_(destination);
+      this.destinationsInserted_();
     }
   }
 
   /**
    * Inserts multiple {@code destinations} to the data store and dispatches
    * single DESTINATIONS_INSERTED event.
-   * @param {!Array<!Destination |
-   *                !Array<Destination>>} destinations Print
-   *     destinations to insert.
-   * @private
    */
-  insertDestinations_(destinations) {
+  private insertDestinations_(destinations: (Destination|null)[]) {
     let inserted = false;
     destinations.forEach(destination => {
-      if (Array.isArray(destination)) {
-        // privet printers return arrays of 1 or 2 printers
-        inserted = destination.reduce(function(soFar, d) {
-          return this.insertIntoStore_(d) || soFar;
-        }, inserted);
-      } else {
-        inserted = this.insertIntoStore_(destination) || inserted;
+      if (destination) {
+        inserted = this.insertIntoStore_(destination!) || inserted;
       }
     });
     if (inserted) {
@@ -938,14 +908,10 @@
    * Dispatches DESTINATIONS_INSERTED event. In auto select mode, tries to
    * update selected destination to match
    * {@code autoSelectMatchingDestination_}.
-   * @param {Destination=} opt_destination The only destination
-   *     that was changed or skipped if possibly more than one destination was
-   *     changed. Used as a hint to limit destination search scope against
-   *     {@code autoSelectMatchingDestination_}.
    */
-  destinationsInserted_(opt_destination) {
+  private destinationsInserted_() {
     this.dispatchEvent(
-        new CustomEvent(DestinationStore.EventType.DESTINATIONS_INSERTED));
+        new CustomEvent(DestinationStoreEventType.DESTINATIONS_INSERTED));
 
     this.tryToSelectInitialDestination_();
   }
@@ -953,29 +919,26 @@
   /**
    * Sends SELECTED_DESTINATION_CAPABILITIES_READY event if the destination
    * is supported, or ERROR otherwise of with error type UNSUPPORTED.
-   * @private
    */
-  sendSelectedDestinationUpdateEvent_() {
-    if (this.selectedDestination_.shouldShowInvalidCertificateError) {
+  private sendSelectedDestinationUpdateEvent_() {
+    if (this.selectedDestination_!.shouldShowInvalidCertificateError) {
       this.dispatchEvent(new CustomEvent(
-          DestinationStore.EventType.ERROR,
+          DestinationStoreEventType.ERROR,
           {detail: DestinationErrorType.UNSUPPORTED}));
     } else {
       this.dispatchEvent(new CustomEvent(
-          DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY));
+          DestinationStoreEventType.SELECTED_DESTINATION_CAPABILITIES_READY));
     }
   }
 
   /**
    * Updates an existing print destination with capabilities and display name
    * information. If the destination doesn't already exist, it will be added.
-   * @param {!Destination} destination Destination to update.
-   * @private
    */
-  updateDestination_(destination) {
+  private updateDestination_(destination: Destination) {
     assert(destination.constructor !== Array, 'Single printer expected');
     destination.capabilities =
-        localizeCapabilities(assert(destination.capabilities));
+        localizeCapabilities(assert(destination.capabilities!));
     if (originToType(destination.origin) !== PrinterType.LOCAL_PRINTER) {
       destination.capabilities = sortMediaSizes(destination.capabilities);
     }
@@ -995,13 +958,9 @@
 
   /**
    * Inserts a destination into the store without dispatching any events.
-   * @param {!Destination} destination The destination to be
-   *     inserted.
-   * @return {boolean} Whether the inserted destination was not already in the
-   *     store.
-   * @private
+   * @return Whether the inserted destination was not already in the store.
    */
-  insertIntoStore_(destination) {
+  private insertIntoStore_(destination: Destination): boolean {
     const key = destination.key;
     const existingDestination = this.destinationMap_.get(key);
     if (existingDestination === undefined) {
@@ -1020,11 +979,8 @@
 
   /**
    * Creates a local PDF print destination.
-   * @private
    */
-  createLocalPdfPrintDestination_() {
-    // TODO(alekseys): Create PDF printer in the native code and send its
-    // capabilities back with other local printers.
+  private createLocalPdfPrintDestination_() {
     if (this.pdfPrinterEnabled_) {
       this.insertDestination_(new Destination(
           GooglePromotedDestinationId.SAVE_AS_PDF, DestinationType.LOCAL,
@@ -1039,9 +995,8 @@
   // <if expr="chromeos or lacros">
   /**
    * Creates a local Drive print destination.
-   * @private
    */
-  createLocalDrivePrintDestination_() {
+  private createLocalDrivePrintDestination_() {
     this.insertDestination_(new Destination(
         GooglePromotedDestinationId.SAVE_TO_DRIVE_CROS, DestinationType.LOCAL,
         DestinationOrigin.LOCAL, loadTimeData.getString('printToGoogleDrive'),
@@ -1051,16 +1006,15 @@
 
   /**
    * Called when destination search is complete for some type of printer.
-   * @param {!PrinterType} type The type of printers that are
-   *     done being retrieved.
+   * @param type The type of printers that are done being retrieved.
    */
-  onDestinationSearchDone_(type) {
+  private onDestinationSearchDone_(type: PrinterType) {
     MetricsContext.getPrinters(type).record(
         Metrics.PrintPreviewInitializationEvents.FUNCTION_SUCCESSFUL);
     this.destinationSearchStatus_.set(
         type, DestinationStorePrinterSearchStatus.DONE);
     this.dispatchEvent(
-        new CustomEvent(DestinationStore.EventType.DESTINATION_SEARCH_DONE));
+        new CustomEvent(DestinationStoreEventType.DESTINATION_SEARCH_DONE));
     if (this.typesToSearch_.has(type)) {
       this.typesToSearch_.delete(type);
       this.tryToSelectInitialDestination_();
@@ -1074,15 +1028,15 @@
    * local destination. Updates the destination with new capabilities if the
    * destination already exists, otherwise it creates a new destination and
    * then updates its capabilities.
-   * @param {!DestinationOrigin} origin The origin of the
-   *     print destination.
-   * @param {string} id The id of the print destination.
-   * @param {!CapabilitiesResponse} settingsInfo Contains
-   *     the capabilities of the print destination, and information about
-   *     the destination except in the case of extension printers.
-   * @private
+   * @param origin The origin of the print destination.
+   * @param id The id of the print destination.
+   * @param settingsInfo Contains the capabilities of the print destination,
+   *     and information about the destination except in the case of extension
+   *     printers.
    */
-  onCapabilitiesSet_(origin, id, settingsInfo) {
+  private onCapabilitiesSet_(
+      origin: DestinationOrigin, id: string,
+      settingsInfo: CapabilitiesResponse) {
     MetricsContext.getPrinterCapabilities().record(
         Metrics.PrintPreviewInitializationEvents.FUNCTION_SUCCESSFUL);
     let dest = null;
@@ -1119,12 +1073,11 @@
    * Called when a request to get a local destination's print capabilities
    * fails. If the destination is the initial destination, auto-select another
    * destination instead.
-   * @param {DestinationOrigin} origin The origin type of the
-   *     failed destination.
-   * @param {string} destinationId The destination ID that failed.
-   * @private
+   * @param _origin The origin type of the failed destination.
+   * @param destinationId The destination ID that failed.
    */
-  onGetCapabilitiesFail_(origin, destinationId) {
+  private onGetCapabilitiesFail_(
+      _origin: DestinationOrigin, destinationId: string) {
     MetricsContext.getPrinterCapabilities().record(
         Metrics.PrintPreviewInitializationEvents.FUNCTION_FAILED);
     console.warn(
@@ -1132,7 +1085,7 @@
     if (this.selectedDestination_ &&
         this.selectedDestination_.id === destinationId) {
       this.dispatchEvent(new CustomEvent(
-          DestinationStore.EventType.ERROR,
+          DestinationStoreEventType.ERROR,
           {detail: DestinationErrorType.INVALID}));
     }
   }
@@ -1140,15 +1093,14 @@
   /**
    * Called when the /search call completes, either successfully or not.
    * In case of success, stores fetched destinations.
-   * @param {!CustomEvent<!CloudPrintInterfaceSearchDoneDetail>}
-   *      event Contains the request result.
-   * @private
+   * @param event Contains the request result.
    */
-  onCloudPrintSearchDone_(event) {
+  private onCloudPrintSearchDone_(
+      event: CustomEvent<CloudPrintInterfaceSearchDoneDetail>) {
     const payload = event.detail;
     const searchingCloudPrintersDone =
         this.typesToSearch_.has(PrinterType.CLOUD_PRINTER) &&
-        !this.cloudPrintInterface_.isCloudDestinationSearchInProgress() &&
+        !this.cloudPrintInterface_!.isCloudDestinationSearchInProgress() &&
         (!!payload.user ||
          event.type === CloudPrintInterfaceEventType.SEARCH_FAILED);
     if (searchingCloudPrintersDone) {
@@ -1168,17 +1120,15 @@
       }
     }
     this.dispatchEvent(
-        new CustomEvent(DestinationStore.EventType.DESTINATION_SEARCH_DONE));
+        new CustomEvent(DestinationStoreEventType.DESTINATION_SEARCH_DONE));
   }
 
   /**
    * Called when /printer call completes. Updates the specified destination's
    * print capabilities.
-   * @param {!CustomEvent<!Destination>} event Contains
-   *     detailed information about the destination.
-   * @private
+   * @param event Contains detailed information about the destination.
    */
-  onCloudPrintPrinterDone_(event) {
+  private onCloudPrintPrinterDone_(event: CustomEvent<Destination>) {
     this.updateDestination_(event.detail);
     this.inFlightCloudPrintRequests_.delete(event.detail.key);
   }
@@ -1187,18 +1137,18 @@
    * Called when the Google Cloud Print interface fails to lookup a
    * destination. Selects another destination if the failed destination was
    * the initial destination.
-   * @param {!CustomEvent<!CloudPrintInterfacePrinterFailedDetail>}
-   *     event Contains the ID of the destination that failed to be looked up.
-   * @private
+   * @param event Contains the ID of the destination that failed to be looked
+   *     up.
    */
-  onCloudPrintPrinterFailed_(event) {
+  private onCloudPrintPrinterFailed_(
+      event: CustomEvent<CloudPrintInterfacePrinterFailedDetail>) {
     const key = createDestinationKey(
         event.detail.destinationId, event.detail.origin,
         event.detail.account || '');
     this.inFlightCloudPrintRequests_.delete(key);
     if (this.selectedDestination_ && this.selectedDestination_.key === key) {
       this.dispatchEvent(new CustomEvent(
-          DestinationStore.EventType.ERROR,
+          DestinationStoreEventType.ERROR,
           {detail: DestinationErrorType.INVALID}));
     }
   }
@@ -1206,49 +1156,29 @@
   /**
    * Called when a printer or printers are detected after sending getPrinters
    * from the native layer.
-   * @param {!PrinterType} type The type of printer(s) added.
-   * @param {!Array<!LocalDestinationInfo |
-   *                !ProvisionalDestinationInfo>} printers
-   *     Information about the printers that have been retrieved.
+   * @param type The type of printer(s) added.
+   * @param printers Information about the printers that have been retrieved.
    */
-  onPrintersAdded_(type, printers) {
+  private onPrintersAdded_(
+      type: PrinterType,
+      printers: LocalDestinationInfo[]|ProvisionalDestinationInfo[]) {
     this.insertDestinations_(printers.map(
-        printer =>
-            /** @type {!Destination} */ (parseDestination(type, printer))));
+        (printer: LocalDestinationInfo|ProvisionalDestinationInfo) =>
+            parseDestination(type, printer)));
   }
 }
 
 /**
- * Event types dispatched by the destination store.
- * @enum {string}
- */
-DestinationStore.EventType = {
-  DESTINATION_SEARCH_DONE: 'DestinationStore.DESTINATION_SEARCH_DONE',
-  DESTINATION_SELECT: 'DestinationStore.DESTINATION_SELECT',
-  DESTINATIONS_INSERTED: 'DestinationStore.DESTINATIONS_INSERTED',
-  ERROR: 'DestinationStore.ERROR',
-  SELECTED_DESTINATION_CAPABILITIES_READY: 'DestinationStore' +
-      '.SELECTED_DESTINATION_CAPABILITIES_READY',
-  // <if expr="chromeos or lacros">
-  DESTINATION_EULA_READY: 'DestinationStore.DESTINATION_EULA_READY',
-  // </if>
-};
-
-/**
  * Maximum amount of time spent searching for extension destinations, in
  * milliseconds.
- * @private {number}
- * @const
  */
-DestinationStore.EXTENSION_SEARCH_DURATION_ = 5000;
+const EXTENSION_SEARCH_DURATION_: number = 5000;
 
 /**
  * Human readable names for media sizes in the cloud print CDD.
  * https://developers.google.com/cloud-print/docs/cdd
- * @private {Object<string>}
- * @const
  */
-DestinationStore.MEDIA_DISPLAY_NAMES_ = {
+const MEDIA_DISPLAY_NAMES_: {[key: string]: string} = {
   'ISO_2A0': '2A0',
   'ISO_A0': 'A0',
   'ISO_A0X3': 'A0x3',
diff --git a/chrome/browser/resources/print_preview/data/print_server_store.js b/chrome/browser/resources/print_preview/data/print_server_store.js
deleted file mode 100644
index 13702680..0000000
--- a/chrome/browser/resources/print_preview/data/print_server_store.js
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
-
-import {NativeLayerCros, NativeLayerCrosImpl, PrintServer, PrintServersConfig} from '../native_layer_cros.js';
-
-import {PrinterType} from './destination_match.js';
-import {DestinationStore} from './destination_store.js';
-
-export class PrintServerStore extends EventTarget {
-  /**
-   * A data store that stores print servers and dispatches events when the
-   * data store changes.
-   * @param {function(string, !Function):void} addListenerCallback Function
-   *     to call to add Web UI listeners in PrintServerStore constructor.
-   */
-  constructor(addListenerCallback) {
-    super();
-
-    /**
-     * Used to fetch print servers.
-     * @private {!NativeLayerCros}
-     */
-    this.nativeLayerCros_ = NativeLayerCrosImpl.getInstance();
-
-    /**
-     * All available print servers mapped by name.
-     * @private {!Map<string, !Array<!PrintServer>>}
-     */
-    this.printServersByName_ = new Map();
-
-    /**
-     * Whether in single print server fetching mode.
-     * @private {boolean}
-     */
-    this.isSingleServerFetchingMode_ = false;
-
-    /**
-     * Used to reload local printers.
-     * @private {?DestinationStore}
-     */
-    this.destinationStore_ = null;
-
-    addListenerCallback(
-        'print-servers-config-changed',
-        printServersConfig =>
-            this.onPrintServersConfigChanged_(printServersConfig));
-    addListenerCallback(
-        'server-printers-loading',
-        isLoading => this.onServerPrintersLoading_(isLoading));
-  }
-
-  /**
-   * Selects the print server(s) with the corresponding name.
-   * @param {string} printServerName Name of the print server(s).
-   */
-  choosePrintServers(printServerName) {
-    const printServers = this.printServersByName_.get(printServerName);
-    this.nativeLayerCros_.choosePrintServers(
-        printServers ? printServers.map(printServer => printServer.id) : []);
-  }
-
-  /**
-   * Gets the currently available print servers and fetching mode.
-   * @return {!Promise<!PrintServersConfig>} The print servers configuration.
-   */
-  async getPrintServersConfig() {
-    const printServersConfig =
-        await this.nativeLayerCros_.getPrintServersConfig();
-    this.updatePrintServersConfig(printServersConfig);
-    return printServersConfig;
-  }
-
-  /**
-   * @param {!DestinationStore} destinationStore The destination store.
-   */
-  setDestinationStore(destinationStore) {
-    this.destinationStore_ = destinationStore;
-  }
-
-  /**
-   * Called when new print servers and fetching mode are available.
-   * @param {!PrintServersConfig} printServersConfig The print servers
-   *     configuration.
-   */
-  onPrintServersConfigChanged_(printServersConfig) {
-    this.updatePrintServersConfig(printServersConfig);
-    const eventData = {
-      printServerNames: Array.from(this.printServersByName_.keys()),
-      isSingleServerFetchingMode: this.isSingleServerFetchingMode_
-    };
-    this.dispatchEvent(new CustomEvent(
-        PrintServerStore.EventType.PRINT_SERVERS_CHANGED, {detail: eventData}));
-  }
-
-  /**
-   * Updates the print servers configuration when new print servers and fetching
-   * mode are available.
-   * @param {!PrintServersConfig} printServersConfig The print servers
-   *     configuration.
-   * @private
-   */
-  updatePrintServersConfig(printServersConfig) {
-    this.isSingleServerFetchingMode_ =
-        printServersConfig.isSingleServerFetchingMode;
-    this.printServersByName_ = new Map();
-    for (const printServer of printServersConfig.printServers) {
-      if (this.printServersByName_.has(printServer.name)) {
-        this.printServersByName_.get(printServer.name).push(printServer);
-      } else {
-        this.printServersByName_.set(printServer.name, [printServer]);
-      }
-    }
-  }
-
-  /**
-   * Called when print server printers loading status has changed.
-   * @param {boolean} isLoading Whether server printers are loading
-   */
-  async onServerPrintersLoading_(isLoading) {
-    if (!isLoading && this.destinationStore_) {
-      await this.destinationStore_.reloadLocalPrinters();
-    }
-    this.dispatchEvent(new CustomEvent(
-        PrintServerStore.EventType.SERVER_PRINTERS_LOADING,
-        {detail: isLoading}));
-  }
-}
-
-/**
- * Event types dispatched by the print server store.
- * @enum {string}
- */
-PrintServerStore.EventType = {
-  PRINT_SERVERS_CHANGED: 'PrintServerStore.PRINT_SERVERS_CHANGED',
-  SERVER_PRINTERS_LOADING: 'PrintServerStore.SERVER_PRINTERS_LOADING',
-};
diff --git a/chrome/browser/resources/print_preview/data/print_server_store.ts b/chrome/browser/resources/print_preview/data/print_server_store.ts
new file mode 100644
index 0000000..68fd6554
--- /dev/null
+++ b/chrome/browser/resources/print_preview/data/print_server_store.ts
@@ -0,0 +1,128 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+
+import {NativeLayerCros, NativeLayerCrosImpl, PrintServer, PrintServersConfig} from '../native_layer_cros.js';
+
+import {PrinterType} from './destination_match.js';
+import {DestinationStore} from './destination_store.js';
+
+export class PrintServerStore extends EventTarget {
+  /**
+   * Used to fetch print servers.
+   */
+  private nativeLayerCros_: NativeLayerCros = NativeLayerCrosImpl.getInstance();
+
+  /**
+   * All available print servers mapped by name.
+   */
+  private printServersByName_: Map<string, PrintServer[]> = new Map();
+
+  /**
+   * Whether in single print server fetching mode.
+   */
+  private isSingleServerFetchingMode_: boolean = false;
+
+  /**
+   * Used to reload local printers.
+   */
+  private destinationStore_: DestinationStore|null = null;
+
+  /**
+   * A data store that stores print servers and dispatches events when the
+   * data store changes.
+   * @param addListenerCallback Function to call to add Web UI listeners in
+   *     PrintServerStore constructor.
+   */
+  constructor(
+      addListenerCallback:
+          (eventName: string, listener: (p: any) => void) => void) {
+    super();
+
+    addListenerCallback(
+        'print-servers-config-changed',
+        (printServersConfig: PrintServersConfig) =>
+            this.onPrintServersConfigChanged_(printServersConfig));
+    addListenerCallback(
+        'server-printers-loading',
+        (isLoading: boolean) => this.onServerPrintersLoading_(isLoading));
+  }
+
+  /**
+   * Selects the print server(s) with the corresponding name.
+   * @param printServerName Name of the print server(s).
+   */
+  choosePrintServers(printServerName: string) {
+    const printServers = this.printServersByName_.get(printServerName);
+    this.nativeLayerCros_.choosePrintServers(
+        printServers ? printServers.map(printServer => printServer.id) : []);
+  }
+
+  /**
+   * Gets the currently available print servers and fetching mode.
+   * @return The print servers configuration.
+   */
+  async getPrintServersConfig(): Promise<PrintServersConfig> {
+    const printServersConfig =
+        await this.nativeLayerCros_.getPrintServersConfig();
+    this.updatePrintServersConfig_(printServersConfig);
+    return printServersConfig;
+  }
+
+  setDestinationStore(destinationStore: DestinationStore) {
+    this.destinationStore_ = destinationStore;
+  }
+
+  /**
+   * Called when new print servers and fetching mode are available.
+   */
+  private onPrintServersConfigChanged_(printServersConfig: PrintServersConfig) {
+    this.updatePrintServersConfig_(printServersConfig);
+    const eventData = {
+      printServerNames: Array.from(this.printServersByName_.keys()),
+      isSingleServerFetchingMode: this.isSingleServerFetchingMode_
+    };
+    this.dispatchEvent(new CustomEvent(
+        PrintServerStoreEventType.PRINT_SERVERS_CHANGED, {detail: eventData}));
+  }
+
+  /**
+   * Updates the print servers configuration when new print servers and fetching
+   * mode are available.
+   */
+  private updatePrintServersConfig_(printServersConfig: PrintServersConfig) {
+    this.isSingleServerFetchingMode_ =
+        printServersConfig.isSingleServerFetchingMode;
+    this.printServersByName_ = new Map();
+    for (const printServer of printServersConfig.printServers) {
+      if (this.printServersByName_.has(printServer.name)) {
+        this.printServersByName_.get(printServer.name)!.push(printServer);
+      } else {
+        this.printServersByName_.set(printServer.name, [printServer]);
+      }
+    }
+  }
+
+  /**
+   * Called when print server printers loading status has changed.
+   * @param isLoading Whether server printers are loading
+   */
+  private async onServerPrintersLoading_(isLoading: boolean) {
+    if (!isLoading && this.destinationStore_) {
+      await this.destinationStore_.reloadLocalPrinters();
+    }
+    this.dispatchEvent(new CustomEvent(
+        PrintServerStoreEventType.SERVER_PRINTERS_LOADING,
+        {detail: isLoading}));
+  }
+}
+
+/**
+ * Event types dispatched by the print server store.
+ */
+export enum PrintServerStoreEventType {
+  PRINT_SERVERS_CHANGED = 'PrintServerStore.PRINT_SERVERS_CHANGED',
+  SERVER_PRINTERS_LOADING = 'PrintServerStore.SERVER_PRINTERS_LOADING',
+}
diff --git a/chrome/browser/resources/print_preview/data/printer_status_cros.js b/chrome/browser/resources/print_preview/data/printer_status_cros.ts
similarity index 73%
rename from chrome/browser/resources/print_preview/data/printer_status_cros.js
rename to chrome/browser/resources/print_preview/data/printer_status_cros.ts
index b9629cf..6f82faf 100644
--- a/chrome/browser/resources/print_preview/data/printer_status_cros.js
+++ b/chrome/browser/resources/print_preview/data/printer_status_cros.ts
@@ -6,68 +6,64 @@
 /**
  *  These values must be kept in sync with the Reason enum in
  *  /chromeos/printing/cups_printer_status.h
- *  @enum {number}
  */
-export const PrinterStatusReason = {
-  UNKNOWN_REASON: 0,
-  DEVICE_ERROR: 1,
-  DOOR_OPEN: 2,
-  LOW_ON_INK: 3,
-  LOW_ON_PAPER: 4,
-  NO_ERROR: 5,
-  OUT_OF_INK: 6,
-  OUT_OF_PAPER: 7,
-  OUTPUT_ALMOST_FULL: 8,
-  OUTPUT_FULL: 9,
-  PAPER_JAM: 10,
-  PAUSED: 11,
-  PRINTER_QUEUE_FULL: 12,
-  PRINTER_UNREACHABLE: 13,
-  STOPPED: 14,
-  TRAY_MISSING: 15,
-};
+export enum PrinterStatusReason {
+  UNKNOWN_REASON = 0,
+  DEVICE_ERROR = 1,
+  DOOR_OPEN = 2,
+  LOW_ON_INK = 3,
+  LOW_ON_PAPER = 4,
+  NO_ERROR = 5,
+  OUT_OF_INK = 6,
+  OUT_OF_PAPER = 7,
+  OUTPUT_ALMOST_FULL = 8,
+  OUTPUT_FULL = 9,
+  PAPER_JAM = 10,
+  PAUSED = 11,
+  PRINTER_QUEUE_FULL = 12,
+  PRINTER_UNREACHABLE = 13,
+  STOPPED = 14,
+  TRAY_MISSING = 15,
+}
 
 /**
  *  These values must be kept in sync with the Severity enum in
  *  /chromeos/printing/cups_printer_status.h
- *  @enum {number}
  */
-export const PrinterStatusSeverity = {
-  UNKNOWN_SEVERITY: 0,
-  REPORT: 1,
-  WARNING: 2,
-  ERROR: 3,
-};
+export enum PrinterStatusSeverity {
+  UNKNOWN_SEVERITY = 0,
+  REPORT = 1,
+  WARNING = 2,
+  ERROR = 3,
+}
 
 /**
  * Enumeration giving a local Chrome OS printer 3 different state possibilities
  * depending on its current status.
- * @enum {number}
  */
-export const PrinterState = {
-  GOOD: 0,
-  ERROR: 1,
-  UNKNOWN: 2,
+export enum PrinterState {
+  GOOD = 0,
+  ERROR = 1,
+  UNKNOWN = 2,
+}
+
+type StatusReasonEntry = {
+  reason: PrinterStatusReason,
+  severity: PrinterStatusSeverity,
 };
 
 /**
  * A container for the results of a printer status query. A printer status query
  * can return multiple error reasons. |timestamp| is set at the time of status
  * creation.
- *
- * @typedef {{
- *   printerId: string,
- *   statusReasons: !Array<{
- *     reason: PrinterStatusReason,
- *     severity: PrinterStatusSeverity,
- *   }>,
- *   timestamp: number,
- * }}
  */
-export let PrinterStatus;
+export type PrinterStatus = {
+  printerId: string,
+  statusReasons: StatusReasonEntry[],
+  timestamp: number,
+};
 
-/** @const {!Map<!PrinterStatusReason, string>} */
-export const ERROR_STRING_KEY_MAP = new Map([
+export const ERROR_STRING_KEY_MAP: Map<PrinterStatusReason, string> = new Map([
   [PrinterStatusReason.DEVICE_ERROR, 'printerStatusDeviceError'],
   [PrinterStatusReason.DOOR_OPEN, 'printerStatusDoorOpen'],
   [PrinterStatusReason.LOW_ON_INK, 'printerStatusLowOnInk'],
@@ -91,10 +87,10 @@
  * will get highest precedence since this usually means the printer is in a
  * bad state. If there does not exist an error status reason with a high enough
  * severity, then return NO_ERROR.
- * @param {!PrinterStatus} printerStatus
- * @return {!PrinterStatusReason} Status reason extracted from |printerStatus|.
+ * @return Status reason extracted from |printerStatus|.
  */
-export function getStatusReasonFromPrinterStatus(printerStatus) {
+export function getStatusReasonFromPrinterStatus(printerStatus: PrinterStatus):
+    PrinterStatusReason {
   if (!printerStatus.printerId) {
     // TODO(crbug.com/1027400): Remove console.warn once bug is confirmed fix.
     console.warn('Received printer status missing printer id');
@@ -124,12 +120,9 @@
   return statusReason;
 }
 
-/**
- * @param {?PrinterStatusReason} printerStatusReason
- * @return {number}
- */
-export function computePrinterState(printerStatusReason) {
-  if (!printerStatusReason ||
+export function computePrinterState(
+    printerStatusReason: (PrinterStatusReason|null)): PrinterState {
+  if (printerStatusReason === null ||
       printerStatusReason === PrinterStatusReason.UNKNOWN_REASON) {
     return PrinterState.UNKNOWN;
   }
@@ -139,12 +132,9 @@
   return PrinterState.ERROR;
 }
 
-/**
- * @param {?PrinterStatusReason} printerStatusReason
- * @param {boolean} isEnterprisePrinter
- * @return {string}
- */
-export function getPrinterStatusIcon(printerStatusReason, isEnterprisePrinter) {
+export function getPrinterStatusIcon(
+    printerStatusReason: PrinterStatusReason|null,
+    isEnterprisePrinter: boolean): string {
   switch (computePrinterState(printerStatusReason)) {
     case PrinterState.GOOD:
       return isEnterprisePrinter ?
@@ -159,5 +149,6 @@
           'print-preview:printer-status-grey';
     default:
       assertNotReached();
+      return '';
   }
 }
diff --git a/chrome/browser/resources/print_preview/metrics.js b/chrome/browser/resources/print_preview/metrics.js
index 645c428fa..ce50b93 100644
--- a/chrome/browser/resources/print_preview/metrics.js
+++ b/chrome/browser/resources/print_preview/metrics.js
@@ -190,7 +190,7 @@
         histogram = 'PrintPreview.Initialization.GetPrinters.Cloud';
         break;
       default:
-        assertNotReached();
+        assertNotReached('unknown type = ' + type);
     }
     return new MetricsContext(
         histogram,
diff --git a/chrome/browser/resources/print_preview/native_layer.js b/chrome/browser/resources/print_preview/native_layer.js
index d913d01..d770184 100644
--- a/chrome/browser/resources/print_preview/native_layer.js
+++ b/chrome/browser/resources/print_preview/native_layer.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 import {assert} from 'chrome://resources/js/assert.m.js';
-import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
 
 import {Cdd} from './data/cdd.js';
 import {PrinterType} from './data/destination_match.js';
@@ -314,6 +314,17 @@
     chrome.send(
         'metricsHandler:recordInHistogram', [histogram, bucket, maxBucket]);
   }
+
+  /** @return {!NativeLayer} */
+  static getInstance() {
+    return instance || (instance = new NativeLayerImpl());
+  }
+
+  /** @param {!NativeLayer} obj */
+  static setInstance(obj) {
+    instance = obj;
+  }
 }
 
-addSingletonGetter(NativeLayerImpl);
+/** @type {?NativeLayer} */
+let instance = null;
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index c167f67e..a21f451 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -10,15 +10,15 @@
 export {SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from './data/destination.js';
 // </if>
 export {PrinterType} from './data/destination_match.js';
-export {DestinationErrorType, DestinationStore} from './data/destination_store.js';
+export {DestinationErrorType, DestinationStore, DestinationStoreEventType} from './data/destination_store.js';
 export {CustomMarginsOrientation, Margins, MarginsType} from './data/margins.js';
 export {MeasurementSystem, MeasurementSystemUnitType} from './data/measurement_system.js';
 export {DuplexMode, DuplexType, getInstance, PrintPreviewModelElement, whenReady} from './data/model.js';
 // <if expr="chromeos or lacros">
-export {PrintServerStore} from './data/print_server_store.js';
+export {PrintServerStore, PrintServerStoreEventType} from './data/print_server_store.js';
 // </if>
 // <if expr="chromeos or lacros">
-export {PrinterState, PrinterStatus, PrinterStatusReason, PrinterStatusSeverity} from './data/printer_status_cros.js';
+export {PrinterState, PrinterStatusReason, PrinterStatusSeverity} from './data/printer_status_cros.js';
 // </if>
 export {ScalingType} from './data/scaling.js';
 export {Size} from './data/size.js';
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog.js b/chrome/browser/resources/print_preview/ui/destination_dialog.js
index b936428..21069cae 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog.js
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog.js
@@ -28,7 +28,7 @@
 import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Destination} from '../data/destination.js';
-import {DestinationStore} from '../data/destination_store.js';
+import {DestinationStore, DestinationStoreEventType} from '../data/destination_store.js';
 import {Metrics, MetricsContext} from '../metrics.js';
 import {NativeLayerImpl} from '../native_layer.js';
 
@@ -147,10 +147,10 @@
     assert(this.destinations_.length === 0);
     const destinationStore = assert(this.destinationStore);
     this.tracker_.add(
-        destinationStore, DestinationStore.EventType.DESTINATIONS_INSERTED,
+        destinationStore, DestinationStoreEventType.DESTINATIONS_INSERTED,
         this.updateDestinations_.bind(this));
     this.tracker_.add(
-        destinationStore, DestinationStore.EventType.DESTINATION_SEARCH_DONE,
+        destinationStore, DestinationStoreEventType.DESTINATION_SEARCH_DONE,
         this.updateDestinations_.bind(this));
     this.initialized_ = true;
   }
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog_cros.js b/chrome/browser/resources/print_preview/ui/destination_dialog_cros.js
index 28ef041..ce362bfc 100644
--- a/chrome/browser/resources/print_preview/ui/destination_dialog_cros.js
+++ b/chrome/browser/resources/print_preview/ui/destination_dialog_cros.js
@@ -31,8 +31,8 @@
 import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Destination, GooglePromotedDestinationId} from '../data/destination.js';
-import {DestinationStore} from '../data/destination_store.js';
-import {PrintServerStore} from '../data/print_server_store.js';
+import {DestinationStore, DestinationStoreEventType} from '../data/destination_store.js';
+import {PrintServerStore, PrintServerStoreEventType} from '../data/print_server_store.js';
 import {Metrics, MetricsContext} from '../metrics.js';
 import {NativeLayerImpl} from '../native_layer.js';
 import {PrintServer, PrintServersConfig} from '../native_layer_cros.js';
@@ -168,12 +168,11 @@
         (/** string */ eventName, /** !Function */ callback) =>
             void this.addWebUIListener(eventName, callback));
     this.tracker_.add(
-        this.printServerStore_,
-        PrintServerStore.EventType.PRINT_SERVERS_CHANGED,
+        this.printServerStore_, PrintServerStoreEventType.PRINT_SERVERS_CHANGED,
         event => void this.onPrintServersChanged_(event));
     this.tracker_.add(
         this.printServerStore_,
-        PrintServerStore.EventType.SERVER_PRINTERS_LOADING,
+        PrintServerStoreEventType.SERVER_PRINTERS_LOADING,
         event => void this.onServerPrintersLoading_(event));
     this.printServerStore_.getPrintServersConfig().then(config => {
       this.printServerNames_ =
@@ -213,10 +212,10 @@
     assert(this.destinations_.length === 0);
     const destinationStore = assert(this.destinationStore);
     this.tracker_.add(
-        destinationStore, DestinationStore.EventType.DESTINATIONS_INSERTED,
+        destinationStore, DestinationStoreEventType.DESTINATIONS_INSERTED,
         this.updateDestinations_.bind(this));
     this.tracker_.add(
-        destinationStore, DestinationStore.EventType.DESTINATION_SEARCH_DONE,
+        destinationStore, DestinationStoreEventType.DESTINATION_SEARCH_DONE,
         this.updateDestinations_.bind(this));
     this.initialized_ = true;
     if (this.printServerStore_) {
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.js b/chrome/browser/resources/print_preview/ui/destination_settings.js
index 973740d1..1851ed8 100644
--- a/chrome/browser/resources/print_preview/ui/destination_settings.js
+++ b/chrome/browser/resources/print_preview/ui/destination_settings.js
@@ -37,7 +37,7 @@
 import {SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from '../data/destination.js';
 // </if>
 import {getPrinterTypeForDestination, PrinterType} from '../data/destination_match.js';
-import {DestinationErrorType, DestinationStore} from '../data/destination_store.js';
+import {DestinationErrorType, DestinationStore, DestinationStoreEventType} from '../data/destination_store.js';
 import {Error, State} from '../data/state.js';
 
 import {SettingsBehavior, SettingsBehaviorInterface} from './settings_behavior.js';
@@ -196,14 +196,14 @@
     this.destinationStore_ =
         new DestinationStore(this.addWebUIListener.bind(this));
     this.tracker_.add(
-        this.destinationStore_, DestinationStore.EventType.DESTINATION_SELECT,
+        this.destinationStore_, DestinationStoreEventType.DESTINATION_SELECT,
         this.onDestinationSelect_.bind(this));
     this.tracker_.add(
         this.destinationStore_,
-        DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY,
+        DestinationStoreEventType.SELECTED_DESTINATION_CAPABILITIES_READY,
         this.onDestinationCapabilitiesReady_.bind(this));
     this.tracker_.add(
-        this.destinationStore_, DestinationStore.EventType.ERROR,
+        this.destinationStore_, DestinationStoreEventType.ERROR,
         this.onDestinationError_.bind(this));
     // Need to update the recent list when the destination store inserts
     // destinations, in case any recent destinations have been added to the
@@ -212,13 +212,13 @@
     // fetched by the DestinationStore, to ensure that they still exist.
     this.tracker_.add(
         assert(this.destinationStore_),
-        DestinationStore.EventType.DESTINATIONS_INSERTED,
+        DestinationStoreEventType.DESTINATIONS_INSERTED,
         this.updateDropdownDestinations_.bind(this));
 
     // <if expr="chromeos or lacros">
     this.tracker_.add(
         this.destinationStore_,
-        DestinationStore.EventType.DESTINATION_EULA_READY,
+        DestinationStoreEventType.DESTINATION_EULA_READY,
         this.updateDestinationEulaUrl_.bind(this));
     // </if>
   }
diff --git a/chrome/browser/resources/read_later/app.html b/chrome/browser/resources/read_later/app.html
index dbc80e0..8c8cf66 100644
--- a/chrome/browser/resources/read_later/app.html
+++ b/chrome/browser/resources/read_later/app.html
@@ -113,6 +113,7 @@
 
   #empty-state-image {
     content: url(images/read_later_empty.svg);
+    height: 160px;
     margin-bottom: 8px;
     margin-top: 16px;
     width: 240px;
@@ -154,47 +155,49 @@
       on-click="onCloseClick_" title="$i18n{tooltipClose}">
   </cr-icon-button>
 </div>
-<div id="empty-state-container"
-     hidden="[[!isReadingListEmpty_(unreadItems_, readItems_)]]">
-  <img id="empty-state-image" aria-hidden="true">
-  <div id="empty-state-header">$i18n{emptyStateHeader}</div>
-  <div id="empty-state-subheader">[[getEmptyStateSubheaderText_()]]</div>
-</div>
-<cr-button id="currentPageActionButton"
-    hidden$="[[!shouldShowCurrentPageActionButton_()]]"
-    aria-label="$i18n{addCurrentTab}"
-    on-click="onCurrentPageActionButtonClick_"
-    disabled="[[getCurrentPageActionButtonDisabled_(
-        currentPageActionButtonState_)]]">
-  <iron-icon id="currentPageActionButtonIcon" aria-hidden="true"
-      icon="cr:add">
-  </iron-icon>
-  <div id="currentPageActionButtonText" aria-hidden="true">
-    $i18n{addCurrentTab}
+<div id="content" hidden="[[loadingContent_]]">
+  <div id="empty-state-container"
+       hidden="[[!isReadingListEmpty_(unreadItems_, readItems_)]]">
+    <img id="empty-state-image" aria-hidden="true">
+    <div id="empty-state-header">$i18n{emptyStateHeader}</div>
+    <div id="empty-state-subheader">[[getEmptyStateSubheaderText_()]]</div>
   </div>
-</cr-button>
-<div id="readLaterList">
-  <iron-selector id="selector" on-keydown="onItemKeyDown_"
-      attr-for-selected="data-url" selectable="read-later-item">
-    <div hidden="[[!unreadItems_.length]]" class="sub-heading">
-      $i18n{unreadHeader}
+  <cr-button id="currentPageActionButton"
+      hidden$="[[!shouldShowCurrentPageActionButton_()]]"
+      aria-label="$i18n{addCurrentTab}"
+      on-click="onCurrentPageActionButtonClick_"
+      disabled="[[getCurrentPageActionButtonDisabled_(
+          currentPageActionButtonState_)]]">
+    <iron-icon id="currentPageActionButtonIcon" aria-hidden="true"
+        icon="cr:add">
+    </iron-icon>
+    <div id="currentPageActionButtonText" aria-hidden="true">
+      $i18n{addCurrentTab}
     </div>
-    <template id="ureadItemsList" is="dom-repeat" items="[[unreadItems_]]">
-      <read-later-item data-url$="[[item.url.url]]" on-focus="onItemFocus_"
-          aria-label="[[ariaLabel_(item)]]" class="mwb-list-item"
-          data="[[item]]" button-ripples="[[buttonRipples]]" tabindex="0">
-      </read-later-item>
-    </template>
-    <div class="hr" hidden$="[[!shouldShowHr_(unreadItems_, readItems_)]]">
-    </div>
-    <div hidden="[[!readItems_.length]]" class="sub-heading">
-      $i18n{readHeader}
-    </div>
-    <template id="readItemsList" is="dom-repeat" items="[[readItems_]]">
-      <read-later-item data-url$="[[item.url.url]]" on-focus="onItemFocus_"
-          aria-label="[[ariaLabel_(item)]]" class="mwb-list-item"
-          data="[[item]]" button-ripples="[[buttonRipples]]" tabindex="0">
-      </read-later-item>
-    </template>
-  </iron-selector>
+  </cr-button>
+  <div id="readLaterList">
+    <iron-selector id="selector" on-keydown="onItemKeyDown_"
+        attr-for-selected="data-url" selectable="read-later-item">
+      <div hidden="[[!unreadItems_.length]]" class="sub-heading">
+        $i18n{unreadHeader}
+      </div>
+      <template id="ureadItemsList" is="dom-repeat" items="[[unreadItems_]]">
+        <read-later-item data-url$="[[item.url.url]]" on-focus="onItemFocus_"
+            aria-label="[[ariaLabel_(item)]]" class="mwb-list-item"
+            data="[[item]]" button-ripples="[[buttonRipples]]" tabindex="0">
+        </read-later-item>
+      </template>
+      <div class="hr" hidden$="[[!shouldShowHr_(unreadItems_, readItems_)]]">
+      </div>
+      <div hidden="[[!readItems_.length]]" class="sub-heading">
+        $i18n{readHeader}
+      </div>
+      <template id="readItemsList" is="dom-repeat" items="[[readItems_]]">
+        <read-later-item data-url$="[[item.url.url]]" on-focus="onItemFocus_"
+            aria-label="[[ariaLabel_(item)]]" class="mwb-list-item"
+            data="[[item]]" button-ripples="[[buttonRipples]]" tabindex="0">
+        </read-later-item>
+      </template>
+    </iron-selector>
+  </div>
 </div>
diff --git a/chrome/browser/resources/read_later/app.js b/chrome/browser/resources/read_later/app.js
index 94b0bc8..7ee35865 100644
--- a/chrome/browser/resources/read_later/app.js
+++ b/chrome/browser/resources/read_later/app.js
@@ -58,6 +58,12 @@
         type: Boolean,
         value: () => loadTimeData.getBoolean('useRipples'),
       },
+
+      /** @private {boolean} */
+      loadingContent_: {
+        type: Boolean,
+        value: true,
+      },
     };
   }
 
@@ -144,6 +150,7 @@
   updateItems_(entries) {
     this.unreadItems_ = entries.unreadEntries;
     this.readItems_ = entries.readEntries;
+    this.loadingContent_ = false;
   }
 
   /**
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 2dab315..b4df0e6 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -153,11 +153,11 @@
     "settings.ts",
     "settings_page/main_page_mixin.js",
     "settings_routes.js",
-    "site_settings/constants.js",
-    "site_settings/cookie_info.js",
-    "site_settings/local_data_browser_proxy.js",
-    "site_settings/site_settings_mixin.js",
-    "site_settings/site_settings_prefs_browser_proxy.js",
+    "site_settings/constants.ts",
+    "site_settings/cookie_info.ts",
+    "site_settings/local_data_browser_proxy.ts",
+    "site_settings/site_settings_mixin.ts",
+    "site_settings/site_settings_prefs_browser_proxy.ts",
     "site_settings/website_usage_browser_proxy.ts",
 
     # Files holding TypeScript types, necessary only during the migration. These
@@ -310,7 +310,7 @@
     "site_settings/add_site_dialog.ts",
     "site_settings/all_sites.ts",
     "site_settings/all_sites_icons.ts",
-    "site_settings/category_default_setting.js",
+    "site_settings/category_default_setting.ts",
     "site_settings/category_setting_exceptions.ts",
     "site_settings/chooser_exception_list.ts",
     "site_settings/chooser_exception_list_entry.ts",
@@ -320,9 +320,9 @@
     "site_settings/pdf_documents.ts",
     "site_settings/protocol_handlers.ts",
     "site_settings/settings_category_default_radio_group.ts",
-    "site_settings/site_data.js",
+    "site_settings/site_data.ts",
     "site_settings/site_data_details_subpage.ts",
-    "site_settings/site_data_entry.js",
+    "site_settings/site_data_entry.ts",
     "site_settings/site_details.ts",
     "site_settings/site_details_permission.ts",
     "site_settings/site_entry.ts",
@@ -395,7 +395,6 @@
     "settings_menu:closure_compile",
     "settings_page:closure_compile",
     "settings_ui:closure_compile",
-    "site_settings:closure_compile",
   ]
 
   if (!is_chromeos_ash) {
@@ -478,13 +477,9 @@
 js_library("lazy_load") {
   sources =
       [ "$root_gen_dir/chrome/browser/resources/settings/tsc/lazy_load.js" ]
-  deps = [
-    "site_settings:local_data_browser_proxy",
-    "site_settings:site_settings_prefs_browser_proxy",
-  ]
 
   if (!is_chromeos_ash) {
-    deps += [
+    deps = [
       "languages_page:languages_browser_proxy",
       "languages_page:languages_page",
       "languages_page:languages_settings_metrics_proxy",
@@ -780,15 +775,15 @@
     "site_settings/add_site_dialog.ts",
     "site_settings/all_sites_icons.ts",
     "site_settings/all_sites.ts",
-    "site_settings/category_default_setting.js",
+    "site_settings/category_default_setting.ts",
     "site_settings/category_setting_exceptions.ts",
     "site_settings/chooser_exception_list_entry.ts",
     "site_settings/chooser_exception_list.ts",
     "site_settings/clear_storage_dialog_css.ts",
-    "site_settings/constants.js",
-    "site_settings/cookie_info.js",
+    "site_settings/constants.ts",
+    "site_settings/cookie_info.ts",
     "site_settings/edit_exception_dialog.ts",
-    "site_settings/local_data_browser_proxy.js",
+    "site_settings/local_data_browser_proxy.ts",
     "site_settings/media_picker.ts",
     "site_settings_page/recent_site_permissions.ts",
     "site_settings_page/site_settings_list.ts",
@@ -797,15 +792,15 @@
     "site_settings/protocol_handlers.ts",
     "site_settings/settings_category_default_radio_group.ts",
     "site_settings/site_data_details_subpage.ts",
-    "site_settings/site_data_entry.js",
-    "site_settings/site_data.js",
+    "site_settings/site_data_entry.ts",
+    "site_settings/site_data.ts",
     "site_settings/site_details.ts",
     "site_settings/site_details_permission.ts",
     "site_settings/site_entry.ts",
     "site_settings/site_list_entry.ts",
     "site_settings/site_list.ts",
-    "site_settings/site_settings_mixin.js",
-    "site_settings/site_settings_prefs_browser_proxy.js",
+    "site_settings/site_settings_mixin.ts",
+    "site_settings/site_settings_prefs_browser_proxy.ts",
     "site_settings/website_usage_browser_proxy.ts",
     "site_settings/zoom_levels.ts",
   ]
diff --git a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js
index ecaa47c..c094b65f4 100644
--- a/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js
+++ b/chrome/browser/resources/settings/chromeos/internet_page/internet_detail_page.js
@@ -384,7 +384,7 @@
 
   /** @override */
   attached() {
-    if (loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+    if (loadTimeData.getBoolean('syncSettingsCategorizationEnabled')) {
       this.addWebUIListener(
           'os-sync-prefs-changed', this.handleOsSyncPrefsChanged_.bind(this));
       this.osSyncBrowserProxy_.sendOsSyncPrefsChanged();
@@ -401,7 +401,7 @@
     this.networkConfig_ =
         MojoInterfaceProviderImpl.getInstance().getMojoServiceRemote();
 
-    if (loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+    if (loadTimeData.getBoolean('syncSettingsCategorizationEnabled')) {
       this.osSyncBrowserProxy_ = OsSyncBrowserProxyImpl.getInstance();
     } else {
       this.syncBrowserProxy_ = SyncBrowserProxyImpl.getInstance();
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
index ec24344f..55c91a8f4 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_page.js
@@ -111,10 +111,10 @@
 
     this.addWebUIListener(
         'settings.updateMultidevicePageContentData',
-        this.onPageContentDataChanged_.bind(this));
+        (data) => this.onPageContentDataChanged_(data));
 
     this.browserProxy_.getPageContentData().then(
-        this.onInitialPageContentDataFetched_.bind(this));
+        (data) => this.onInitialPageContentDataFetched_(data));
   },
 
   /**
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.html
index f598d0c1..5aff1ab 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.html
@@ -38,7 +38,8 @@
   </localized-link>
 </div>
 <div id="appNotificationsList">
-  <template is="dom-repeat" items="[[appList_]]" as="app">
+  <template is="dom-repeat" items="[[appList_]]" as="app"
+      sort="alphabeticalSort_">
     <app-notification-row app="[[app]]"></app-notification-row>
   </template>
 </div>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.js
index 090e27f..41bd7b7 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_notifications_page/app_notifications_subpage.js
@@ -189,6 +189,17 @@
     this.setQuietMode_();
     event.stopPropagation();
   }
+
+  /**
+   * A function used for sorting languages alphabetically.
+   * @param {!Object} first An app array item.
+   * @param {!Object} second An app array item.
+   * @return {number} The result of the comparison.
+   * @private
+   */
+  alphabeticalSort_(first, second) {
+    return first.title.localeCompare(second.title);
+  }
 }
 
 
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
index 114f9f7..d3599a3 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/BUILD.gn
@@ -178,6 +178,7 @@
     "//ui/webui/resources/cr_components/chromeos/localized_link:localized_link",
     "//ui/webui/resources/cr_elements/cr_toggle:cr_toggle.m",
     "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:load_time_data.m",
     "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
   extra_deps = [ ":os_sync_controls_module" ]
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
index a93cd53..415d378 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.html
@@ -158,8 +158,9 @@
         </settings-subpage>
       </template>
 
-      <!-- Pre-SplitSettingsSync we show the browser's sync controls. -->
-      <template is="dom-if" if="[[!splitSettingsSyncEnabled_]]">
+      <!-- Pre-SyncSettingsCategorization we show the browser's sync controls.
+      -->
+      <template is="dom-if" if="[[!syncSettingsCategorizationEnabled_]]">
         <template is="dom-if" route-path="/syncSetup/advanced">
           <settings-subpage page-title="$i18n{syncAdvancedPageTitle}"
               learn-more-url="$i18n{syncAndGoogleServicesLearnMoreURL}">
@@ -169,8 +170,9 @@
         </template>
       </template>
 
-      <!-- Post-SplitSettingsSync we have separate OS sync controls. -->
-      <template is="dom-if" if="[[splitSettingsSyncEnabled_]]">
+      <!-- Post-SyncSettingsCategorization we have separate OS sync controls.
+      -->
+      <template is="dom-if" if="[[syncSettingsCategorizationEnabled_]]">
         <template is="dom-if" route-path="/osSync">
           <settings-subpage page-title="$i18n{osSyncPageTitle}"
               learn-more-url="$i18n{syncAndGoogleServicesLearnMoreURL}">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
index 34db6cba..65f85ad8 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_people_page.js
@@ -26,10 +26,11 @@
       notify: true,
     },
 
-    splitSettingsSyncEnabled_: {
+    /** @private */
+    syncSettingsCategorizationEnabled_: {
       type: Boolean,
       value() {
-        return loadTimeData.getBoolean('splitSettingsSyncEnabled');
+        return loadTimeData.getBoolean('syncSettingsCategorizationEnabled');
       },
     },
 
@@ -364,7 +365,7 @@
    * @private
    */
   getSyncRowLabel_() {
-    if (this.splitSettingsSyncEnabled_) {
+    if (this.syncSettingsCategorizationEnabled_) {
       return this.i18n('osSyncPageTitle');
     } else {
       return this.i18n('syncAndNonPersonalizedServices');
@@ -485,7 +486,7 @@
 
   /** @private */
   onSyncTap_() {
-    if (this.splitSettingsSyncEnabled_) {
+    if (this.syncSettingsCategorizationEnabled_) {
       settings.Router.getInstance().navigateTo(settings.routes.OS_SYNC);
       return;
     }
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
index 3b12111..e04d0b02 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.html
@@ -4,6 +4,7 @@
 <link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
 <link rel="import" href="chrome://resources/html/assert.html">
 <link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
 <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="../../settings_shared_css.html">
@@ -121,14 +122,16 @@
         </div>
       </div>
 
-      <cr-button id="syncOnOffButton"
-          class="action-button"
-          on-click="onSyncOnOffButtonClick_"
-          aria-labelledby="syncOnOffButton accountTitle accountSubtitle"
-          aria-describedby="featureLabel"
-          deep-link-focus-id$="[[Setting.kSplitSyncOnOff]]">
-        [[getSyncOnOffButtonLabel_(osSyncFeatureEnabled)]]
-      </cr-button>
+      <template is="dom-if" if="[[syncConsentOptionalEnabled_]]" restamp>
+        <cr-button id="syncOnOffButton"
+            class="action-button"
+            on-click="onSyncOnOffButtonClick_"
+            aria-labelledby="syncOnOffButton accountTitle accountSubtitle"
+            aria-describedby="featureLabel"
+            deep-link-focus-id$="[[Setting.kSplitSyncOnOff]]">
+          [[getSyncOnOffButtonLabel_(osSyncFeatureEnabled)]]
+        </cr-button>
+      </template>
     </div>
 
     <div id="featureLabel" class="settings-box">
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
index e84a3faa..6d53b7b 100644
--- a/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
+++ b/chrome/browser/resources/settings/chromeos/os_people_page/os_sync_controls.js
@@ -97,6 +97,14 @@
       type: Object,
       value: () => new Set([chromeos.settings.mojom.Setting.kSplitSyncOnOff]),
     },
+
+    /** @private */
+    syncConsentOptionalEnabled_: {
+      type: Boolean,
+      value() {
+        return loadTimeData.getBoolean('syncConsentOptionalEnabled');
+      },
+    },
   },
 
   /** @private {?settings.OsSyncBrowserProxy} */
@@ -219,6 +227,7 @@
    * @private
    */
   handleOsSyncPrefsChanged_(osSyncFeatureEnabled, osSyncPrefs) {
+    assert(osSyncFeatureEnabled || this.syncConsentOptionalEnabled_);
     this.osSyncFeatureEnabled = osSyncFeatureEnabled;
     this.osSyncPrefs = osSyncPrefs;
 
@@ -239,6 +248,7 @@
 
   /** @private */
   onSyncOnOffButtonClick_() {
+    assert(this.syncConsentOptionalEnabled_);
     this.browserProxy_.setOsSyncFeatureEnabled(!this.osSyncFeatureEnabled);
     settings.recordSettingChange();
   },
diff --git a/chrome/browser/resources/settings/chromeos/os_route.js b/chrome/browser/resources/settings/chromeos/os_route.js
index 00d6d96..6183e573 100644
--- a/chrome/browser/resources/settings/chromeos/os_route.js
+++ b/chrome/browser/resources/settings/chromeos/os_route.js
@@ -99,14 +99,14 @@
           createSection(r.BASIC, mojom.PEOPLE_SECTION_PATH, Section.kPeople);
       r.ACCOUNT_MANAGER = createSubpage(
           r.OS_PEOPLE, mojom.MY_ACCOUNTS_SUBPAGE_PATH, Subpage.kMyAccounts);
-      if (loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+      if (loadTimeData.getBoolean('syncSettingsCategorizationEnabled')) {
         r.OS_SYNC =
             createSubpage(r.OS_PEOPLE, mojom.SYNC_SUBPAGE_PATH, Subpage.kSync);
       }
       r.SYNC = createSubpage(
           r.OS_PEOPLE, mojom.SYNC_DEPRECATED_SUBPAGE_PATH,
           Subpage.kSyncDeprecated);
-      if (!loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+      if (!loadTimeData.getBoolean('syncSettingsCategorizationEnabled')) {
         r.SYNC_ADVANCED = createSubpage(
             r.SYNC, mojom.SYNC_DEPRECATED_ADVANCED_SUBPAGE_PATH,
             Subpage.kSyncDeprecatedAdvanced);
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn
index 33ba60a..287f3026 100644
--- a/chrome/browser/resources/settings/site_settings/BUILD.gn
+++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -2,107 +2,14 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/polymer/html_to_js.gni")
-import("../settings.gni")
-
-js_type_check("closure_compile") {
-  is_polymer3 = true
-  closure_flags = settings_closure_flags
-  deps = [
-    ":category_default_setting",
-    ":constants",
-    ":cookie_info",
-    ":local_data_browser_proxy",
-    ":site_data",
-    ":site_data_entry",
-    ":site_settings_mixin",
-    ":site_settings_prefs_browser_proxy",
-  ]
-}
-
-js_library("category_default_setting") {
-  deps = [
-    ":constants",
-    ":site_settings_mixin",
-    "..:route",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:load_time_data.m",
-    "//ui/webui/resources/js:web_ui_listener_behavior.m",
-  ]
-  externs_list = [ "$externs_path/settings_private.js" ]
-}
-
-js_library("constants") {
-}
-
-js_library("cookie_info") {
-  deps = [ "//ui/webui/resources/js:load_time_data.m" ]
-}
-
-js_library("local_data_browser_proxy") {
-  deps = [
-    ":cookie_info",
-    "//ui/webui/resources/js:cr.m",
-  ]
-}
-
-js_library("site_data") {
-  deps = [
-    ":local_data_browser_proxy",
-    ":site_settings_mixin",
-    "..:base_mixin",
-    "..:global_scroll_target_mixin",
-    "..:metrics_browser_proxy",
-    "..:route",
-    "//third_party/polymer/v3_0/components-chromium/iron-list:iron-list",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/cr_elements/cr_search_field:cr_search_field",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:cr.m",
-    "//ui/webui/resources/js:list_property_update_behavior.m",
-    "//ui/webui/resources/js:web_ui_listener_behavior.m",
-    "//ui/webui/resources/js/cr/ui:focus_without_ink.m",
-  ]
-}
-
-js_library("site_data_entry") {
-  deps = [
-    ":local_data_browser_proxy",
-    "..:metrics_browser_proxy",
-    "//ui/webui/resources/js:i18n_behavior.m",
-    "//ui/webui/resources/js:icon",
-    "//ui/webui/resources/js/cr/ui:focus_row_behavior.m",
-  ]
-}
-
-js_library("site_settings_mixin") {
-  deps = [
-    ":constants",
-    ":site_settings_prefs_browser_proxy",
-    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
-    "//ui/webui/resources/js:assert.m",
-    "//ui/webui/resources/js:icon",
-    "//ui/webui/resources/js:load_time_data.m",
-  ]
-}
-
-js_library("site_settings_prefs_browser_proxy") {
-  deps = [
-    ":constants",
-    "//ui/webui/resources/cr_elements/policy:cr_policy_indicator_behavior.m",
-    "//ui/webui/resources/js:cr.m",
-  ]
-  externs_list = [ "$externs_path/settings_private.js" ]
-}
 
 html_to_js("web_components") {
   js_files = [
     "add_site_dialog.ts",
     "all_sites.ts",
     "all_sites_icons.ts",
-    "category_default_setting.js",
+    "category_default_setting.ts",
     "category_setting_exceptions.ts",
     "chooser_exception_list.ts",
     "chooser_exception_list_entry.ts",
@@ -112,9 +19,9 @@
     "pdf_documents.ts",
     "protocol_handlers.ts",
     "settings_category_default_radio_group.ts",
-    "site_data.js",
+    "site_data.ts",
     "site_data_details_subpage.ts",
-    "site_data_entry.js",
+    "site_data_entry.ts",
     "site_details.ts",
     "site_details_permission.ts",
     "site_entry.ts",
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.ts b/chrome/browser/resources/settings/site_settings/all_sites.ts
index eee1da5..39824b59 100644
--- a/chrome/browser/resources/settings/site_settings/all_sites.ts
+++ b/chrome/browser/resources/settings/site_settings/all_sites.ts
@@ -211,10 +211,11 @@
     this.addEventListener('open-menu', this.onOpenMenu_.bind(this));
 
     const sortParam = Router.getInstance().getQueryParameters().get('sort');
-    if (sortParam !== null && Object.values(SortMethod).includes(sortParam)) {
+    if (sortParam !== null &&
+        Object.values(SortMethod).includes(sortParam as SortMethod)) {
       this.$.sortMethod.value = sortParam;
     }
-    this.sortMethod_ = this.$.sortMethod.value;
+    this.sortMethod_ = this.$.sortMethod.value as (SortMethod | undefined);
   }
 
   connectedCallback() {
@@ -376,7 +377,7 @@
    * Called when the user chooses a different sort method to the default.
    */
   private onSortMethodChanged_() {
-    this.sortMethod_ = this.$.sortMethod.value;
+    this.sortMethod_ = this.$.sortMethod.value as SortMethod;
     this.filteredList_ = this.sortSiteGroupList_(this.filteredList_);
     // Force the iron-list to rerender its items, as the order has changed.
     this.$.allSitesList.fire('iron-resize');
@@ -699,7 +700,7 @@
    * @param origin The origin of the target origin that should be cleared.
    */
   private clearDataForOrigin_(index: number, origin: string) {
-    this.browserProxy.clearOriginDataAndCookies(this.toUrl(origin).href);
+    this.browserProxy.clearOriginDataAndCookies(this.toUrl(origin)!.href);
 
     const siteGroupToUpdate = this.filteredList_[index];
     const updatedSiteGroup: SiteGroup = {
@@ -746,7 +747,7 @@
    */
   private onClearData_(e: Event) {
     const {index, actionScope, origin} = this.actionMenuModel_!;
-    const scopes = [ALL_SITES_DIALOG.CLEAR_DATA];
+    const scopes: Array<string> = [ALL_SITES_DIALOG.CLEAR_DATA];
 
     if (actionScope === 'origin') {
       this.browserProxy.recordAction(AllSitesAction2.CLEAR_ORIGIN_DATA);
diff --git a/chrome/browser/resources/settings/site_settings/category_default_setting.js b/chrome/browser/resources/settings/site_settings/category_default_setting.ts
similarity index 85%
rename from chrome/browser/resources/settings/site_settings/category_default_setting.js
rename to chrome/browser/resources/settings/site_settings/category_default_setting.ts
index 8eef615..3c1a95d 100644
--- a/chrome/browser/resources/settings/site_settings/category_default_setting.js
+++ b/chrome/browser/resources/settings/site_settings/category_default_setting.ts
@@ -38,7 +38,7 @@
 import '../settings_shared_css.js';
 
 import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js';
-import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {loadTimeData} from '../i18n_setup.js';
@@ -50,23 +50,19 @@
 
 /**
  * The setting to display as a sub-option, if any.
- * @enum {string}
  */
-const SubOptionMode = {
-  PREF: 'pref',
-  NONE: 'none',
-};
+enum SubOptionMode {
+  PREF = 'pref',
+  NONE = 'none',
+}
 
-/**
- * @constructor
- * @extends {PolymerElement}
- * @implements {SiteSettingsMixinInterface}
- * @implements {WebUIListenerBehaviorInterface}
- */
 const CategoryDefaultSettingElementBase =
-    mixinBehaviors([WebUIListenerBehavior], SiteSettingsMixin(PolymerElement));
+    mixinBehaviors(
+        [WebUIListenerBehavior], SiteSettingsMixin(PolymerElement)) as {
+      new ():
+          PolymerElement & WebUIListenerBehavior & SiteSettingsMixinInterface
+    };
 
-/** @polymer */
 class CategoryDefaultSettingElement extends CategoryDefaultSettingElementBase {
   static get is() {
     return 'category-default-setting';
@@ -102,12 +98,10 @@
        * set to SubOptionMode.PREF. */
       subOptionPref: Boolean,
 
-      /* Pref based
-      /** @private {chrome.settingsPrivate.PrefObject} */
       controlParams_: {
         type: Object,
         value() {
-          return /** @type {chrome.settingsPrivate.PrefObject} */ ({});
+          return {};
         },
       },
 
@@ -115,21 +109,18 @@
        * The label to be shown next to the toggle (above
        * |optionDescription_|). This will be either toggleOffLabel or
        * toggleOnLabel.
-       * @private
        */
       optionLabel_: String,
 
       /* The second line, shown under the |optionLabel_| line. This will be
        * either toggleOffDescription or toggleOnDescription. (optional)
-       * @private
        */
       optionDescription_: String,
 
-      /** @private {!DefaultContentSetting} */
       priorDefaultContentSetting_: {
         type: Object,
         value() {
-          return /** @type {DefaultContentSetting} */ ({});
+          return {};
         },
       },
     };
@@ -142,25 +133,35 @@
     ];
   }
 
-  /** @override */
+  toggleOffLabel: string;
+  toggleOnLabel: string;
+  toggleOffDescription: string;
+  toggleOnDescription: string;
+  subOptionLabel: string;
+  subOptionDescription: string;
+  subOptionMode: string;
+  subOptionPref: boolean;
+  private controlParams_: chrome.settingsPrivate.PrefObject;
+  private optionLabel_: string;
+  private optionDescription_: string;
+  private priorDefaultContentSetting_: DefaultContentSetting;
+
   ready() {
     super.ready();
 
     this.addWebUIListener(
-        'contentSettingCategoryChanged', this.onCategoryChanged_.bind(this));
+        'contentSettingCategoryChanged', () => this.onCategoryChanged_());
   }
 
-  /** @return {boolean} */
-  get categoryEnabled() {
+  get categoryEnabled(): boolean {
     return !!assert(this.controlParams_).value;
   }
 
   /**
    * A handler for changing the default permission value for a content type.
    * This is also called during page setup after we get the default state.
-   * @private
    */
-  onChangePermissionControl_() {
+  private onChangePermissionControl_() {
     if (this.category === undefined ||
         this.controlParams_.value === undefined) {
       // Do nothing unless all dependencies are defined.
@@ -224,10 +225,8 @@
 
   /**
    * Update the control parameter values from the content settings.
-   * @param {!DefaultContentSetting} update
-   * @private
    */
-  updateControlParams_(update) {
+  private updateControlParams_(update: DefaultContentSetting) {
     // Early out if there is no actual change.
     if (this.priorDefaultContentSetting_.setting === update.setting &&
         this.priorDefaultContentSetting_.source === update.source) {
@@ -235,9 +234,10 @@
     }
     this.priorDefaultContentSetting_ = update;
 
-    const basePref = {
-      'key': 'controlParams',
-      'type': chrome.settingsPrivate.PrefType.BOOLEAN,
+    const basePref: chrome.settingsPrivate.PrefObject = {
+      key: 'controlParams',
+      type: chrome.settingsPrivate.PrefType.BOOLEAN,
+      value: false,
     };
     if (update.source !== undefined &&
         update.source !== ContentSettingProvider.PREFERENCE) {
@@ -263,15 +263,13 @@
     const prefValue = this.computeIsSettingEnabled(update.setting);
     // The controlParams_ must be replaced (rather than just value changes) so
     // that observers will be notified of the change.
-    this.controlParams_ = /** @type {chrome.settingsPrivate.PrefObject} */ (
-        Object.assign({'value': prefValue}, basePref));
+    this.controlParams_ = Object.assign(basePref, {value: prefValue});
   }
 
   /**
    * Handles changes to the category pref and the |category| member variable.
-   * @private
    */
-  onCategoryChanged_() {
+  private onCategoryChanged_() {
     this.browserProxy.getDefaultValueForContentType(this.category)
         .then(defaultValue => {
           this.updateControlParams_(defaultValue);
@@ -285,20 +283,12 @@
         });
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  isToggleDisabled_() {
+  private isToggleDisabled_(): boolean {
     return this.category === ContentSettingsTypes.POPUPS &&
         loadTimeData.getBoolean('isGuest');
   }
 
-  /**
-   * @return {boolean}
-   * @private
-   */
-  showPrefSubOption_(subOptionMode) {
+  private showPrefSubOption_(subOptionMode: SubOptionMode): boolean {
     return (subOptionMode === SubOptionMode.PREF);
   }
 }
diff --git a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts
index 61e81b0..8a9a51f 100644
--- a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts
+++ b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts
@@ -13,8 +13,9 @@
 import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {loadTimeData} from '../i18n_setup.js';
-import {ContentSetting, ContentSettingsTypes, SiteSettingSource} from './constants.js';
+import {ContentSetting, ContentSettingsTypes} from './constants.js';
 import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js';
+import {ContentSettingProvider} from './site_settings_prefs_browser_proxy.js';
 
 const CategorySettingExceptionsElementBase =
     mixinBehaviors(
@@ -145,7 +146,8 @@
 
     this.browserProxy.getDefaultValueForContentType(this.category)
         .then(update => {
-          this.defaultManaged_ = update.source === SiteSettingSource.POLICY;
+          this.defaultManaged_ =
+              update.source === ContentSettingProvider.POLICY;
         });
   }
 
diff --git a/chrome/browser/resources/settings/site_settings/constants.js b/chrome/browser/resources/settings/site_settings/constants.js
deleted file mode 100644
index 93f2ac0..0000000
--- a/chrome/browser/resources/settings/site_settings/constants.js
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * All possible contentSettingsTypes that we currently support configuring in
- * the UI. Both top-level categories and content settings that represent
- * individual permissions under Site Details should appear here.
- * This should be kept in sync with the |kContentSettingsTypeGroupNames| array
- * in chrome/browser/ui/webui/site_settings_helper.cc
- * @enum {string}
- */
-export const ContentSettingsTypes = {
-  ADS: 'ads',
-  AR: 'ar',
-  AUTOMATIC_DOWNLOADS: 'multiple-automatic-downloads',
-  BACKGROUND_SYNC: 'background-sync',
-  BLUETOOTH_DEVICES: 'bluetooth-devices',
-  BLUETOOTH_SCANNING: 'bluetooth-scanning',
-  CAMERA: 'media-stream-camera',
-  CLIPBOARD: 'clipboard',
-  COOKIES: 'cookies',
-  FILE_HANDLING: 'file-handling',
-  FILE_SYSTEM_WRITE: 'file-system-write',
-  FONT_ACCESS: 'font-access',
-  GEOLOCATION: 'location',
-  HID_DEVICES: 'hid-devices',
-  IDLE_DETECTION: 'idle-detection',
-  IMAGES: 'images',
-  JAVASCRIPT: 'javascript',
-  MIC: 'media-stream-mic',  // AKA Microphone.
-  MIDI_DEVICES: 'midi-sysex',
-  MIXEDSCRIPT: 'mixed-script',
-  NOTIFICATIONS: 'notifications',
-  PAYMENT_HANDLER: 'payment-handler',
-  POPUPS: 'popups',
-  PROTECTED_CONTENT: 'protected-content',
-  PROTOCOL_HANDLERS: 'register-protocol-handler',
-  SENSORS: 'sensors',
-  SERIAL_PORTS: 'serial-ports',
-  SOUND: 'sound',
-  USB_DEVICES: 'usb-devices',
-  VR: 'vr',
-  WINDOW_PLACEMENT: 'window-placement',
-  ZOOM_LEVELS: 'zoom-levels',
-};
-
-/**
- * Contains the possible string values for a given ContentSettingsTypes.
- * This should be kept in sync with the |ContentSetting| enum in
- * components/content_settings/core/common/content_settings.h
- * @enum {string}
- */
-export const ContentSetting = {
-  DEFAULT: 'default',
-  ALLOW: 'allow',
-  BLOCK: 'block',
-  ASK: 'ask',
-  SESSION_ONLY: 'session_only',
-  IMPORTANT_CONTENT: 'detect_important_content',
-};
-
-/**
- * All possible ChooserTypes that we currently support configuring in the UI.
- * This should be kept in sync with the |kChooserTypeGroupNames| array in
- * chrome/browser/ui/webui/site_settings_helper.cc
- * @enum {string}
- */
-export const ChooserType = {
-  NONE: '',
-  USB_DEVICES: 'usb-devices-data',
-  SERIAL_PORTS: 'serial-ports-data',
-  HID_DEVICES: 'hid-devices-data',
-  BLUETOOTH_DEVICES: 'bluetooth-devices-data',
-};
-
-/**
- * Possible preference settings for the profile.cookie_controls_mode pref.
- * This should be kept in sync with the |CookieControlsMode| enum in
- * components/content_settings/core/browser/cookie_settings.h
- * @enum {number}
- */
-export const CookieControlsMode = {
-  OFF: 0,
-  BLOCK_THIRD_PARTY: 1,
-  INCOGNITO_ONLY: 2,
-};
-
-/**
- * Contains the possible sources of a ContentSetting.
- * This should be kept in sync with the |SiteSettingSource| enum in
- * chrome/browser/ui/webui/site_settings_helper.h
- * @enum {string}
- */
-export const SiteSettingSource = {
-  ADS_FILTER_BLACKLIST: 'ads-filter-blacklist',
-  ALLOWLIST: 'allowlist',
-  DEFAULT: 'default',
-  EMBARGO: 'embargo',
-  EXTENSION: 'extension',
-  HOSTED_APP: 'HostedApp',
-  INSECURE_ORIGIN: 'insecure-origin',
-  KILL_SWITCH: 'kill-switch',
-  POLICY: 'policy',
-  PREFERENCE: 'preference',
-};
-
-/**
- * Enumeration of states for the notification default setting generated pref.
- * Must be kept in sync with the enum of the same name located in:
- * chrome/browser/content_settings/generated_notification_pref.h
- * @enum {number}
- */
-export const NotificationSetting = {
-  ASK: 0,
-  QUIETER_MESSAGING: 1,
-  BLOCK: 2,
-};
-
-/**
- * A category value to use for the All Sites list.
- * @type {string}
- */
-const ALL_SITES = 'all-sites';
-
-/**
- * An invalid subtype value.
- * @type {string}
- */
-export const INVALID_CATEGORY_SUBTYPE = '';
-
-/**
- * Contains the possible record action types.
- * This should be kept in sync with the |AllSitesAction2| enum in
- * chrome/browser/ui/webui/settings/site_settings_handler.cc
- * @enum {number}
- */
-export const AllSitesAction2 = {
-  LOAD_PAGE: 0,
-  RESET_SITE_GROUP_PERMISSIONS: 1,
-  RESET_ORIGIN_PERMISSIONS: 2,
-  CLEAR_ALL_DATA: 3,
-  CLEAR_SITE_GROUP_DATA: 4,
-  CLEAR_ORIGIN_DATA: 5,
-  ENTER_SITE_DETAILS: 6,
-};
-
-/**
- * Contains the possible sort methods.
- * @enum {string}
- */
-export const SortMethod = {
-  NAME: 'name',
-  MOST_VISITED: 'most-visited',
-  STORAGE: 'data-stored',
-};
-
-/**
- * Contains types of dialogs on the AllSites page,
- * used for logging userActions.
- * @enum {string}
- */
-export const ALL_SITES_DIALOG = {
-  CLEAR_DATA: 'ClearData',
-  RESET_PERMISSIONS: 'ResetPermissions',
-};
-
-/**
- * String representation of the wildcard used for universal
- * match for SiteExceptions.
- * @type {string}
- */
-export const SITE_EXCEPTION_WILDCARD = '*';
diff --git a/chrome/browser/resources/settings/site_settings/constants.ts b/chrome/browser/resources/settings/site_settings/constants.ts
new file mode 100644
index 0000000..15e1c54
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/constants.ts
@@ -0,0 +1,165 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * All possible contentSettingsTypes that we currently support configuring in
+ * the UI. Both top-level categories and content settings that represent
+ * individual permissions under Site Details should appear here.
+ * This should be kept in sync with the |kContentSettingsTypeGroupNames| array
+ * in chrome/browser/ui/webui/site_settings_helper.cc
+ */
+export enum ContentSettingsTypes {
+  ADS = 'ads',
+  AR = 'ar',
+  AUTOMATIC_DOWNLOADS = 'multiple-automatic-downloads',
+  BACKGROUND_SYNC = 'background-sync',
+  BLUETOOTH_DEVICES = 'bluetooth-devices',
+  BLUETOOTH_SCANNING = 'bluetooth-scanning',
+  CAMERA = 'media-stream-camera',
+  CLIPBOARD = 'clipboard',
+  COOKIES = 'cookies',
+  FILE_HANDLING = 'file-handling',
+  FILE_SYSTEM_WRITE = 'file-system-write',
+  FONT_ACCESS = 'font-access',
+  GEOLOCATION = 'location',
+  HID_DEVICES = 'hid-devices',
+  IDLE_DETECTION = 'idle-detection',
+  IMAGES = 'images',
+  JAVASCRIPT = 'javascript',
+  MIC = 'media-stream-mic',  // AKA Microphone.
+  MIDI_DEVICES = 'midi-sysex',
+  MIXEDSCRIPT = 'mixed-script',
+  NOTIFICATIONS = 'notifications',
+  PAYMENT_HANDLER = 'payment-handler',
+  POPUPS = 'popups',
+  PROTECTED_CONTENT = 'protected-content',
+  PROTOCOL_HANDLERS = 'register-protocol-handler',
+  SENSORS = 'sensors',
+  SERIAL_PORTS = 'serial-ports',
+  SOUND = 'sound',
+  USB_DEVICES = 'usb-devices',
+  VR = 'vr',
+  WINDOW_PLACEMENT = 'window-placement',
+  ZOOM_LEVELS = 'zoom-levels',
+
+  // The following item is not in the C++ kContentSettingsTypeGroupNames, but it
+  // is used everywhere where ContentSettingsTypes is used in JS.
+  PDF_DOCUMENTS = 'pdfDocuments',
+}
+
+/**
+ * Contains the possible string values for a given ContentSettingsTypes.
+ * This should be kept in sync with the |ContentSetting| enum in
+ * components/content_settings/core/common/content_settings.h
+ */
+export enum ContentSetting {
+  DEFAULT = 'default',
+  ALLOW = 'allow',
+  BLOCK = 'block',
+  ASK = 'ask',
+  SESSION_ONLY = 'session_only',
+  IMPORTANT_CONTENT = 'detect_important_content',
+}
+
+/**
+ * All possible ChooserTypes that we currently support configuring in the UI.
+ * This should be kept in sync with the |kChooserTypeGroupNames| array in
+ * chrome/browser/ui/webui/site_settings_helper.cc
+ */
+export enum ChooserType {
+  NONE = '',
+  USB_DEVICES = 'usb-devices-data',
+  SERIAL_PORTS = 'serial-ports-data',
+  HID_DEVICES = 'hid-devices-data',
+  BLUETOOTH_DEVICES = 'bluetooth-devices-data',
+}
+
+/**
+ * Possible preference settings for the profile.cookie_controls_mode pref.
+ * This should be kept in sync with the |CookieControlsMode| enum in
+ * components/content_settings/core/browser/cookie_settings.h
+ */
+export enum CookieControlsMode {
+  OFF = 0,
+  BLOCK_THIRD_PARTY = 1,
+  INCOGNITO_ONLY = 2,
+}
+
+/**
+ * Contains the possible sources of a ContentSetting.
+ * This should be kept in sync with the |SiteSettingSource| enum in
+ * chrome/browser/ui/webui/site_settings_helper.h
+ */
+export enum SiteSettingSource {
+  ADS_FILTER_BLACKLIST = 'ads-filter-blacklist',
+  ALLOWLIST = 'allowlist',
+  DEFAULT = 'default',
+  EMBARGO = 'embargo',
+  EXTENSION = 'extension',
+  HOSTED_APP = 'HostedApp',
+  INSECURE_ORIGIN = 'insecure-origin',
+  KILL_SWITCH = 'kill-switch',
+  POLICY = 'policy',
+  PREFERENCE = 'preference',
+}
+
+/**
+ * Enumeration of states for the notification default setting generated pref.
+ * Must be kept in sync with the enum of the same name located in:
+ * chrome/browser/content_settings/generated_notification_pref.h
+ */
+export enum NotificationSetting {
+  ASK = 0,
+  QUIETER_MESSAGING = 1,
+  BLOCK = 2,
+}
+
+/**
+ * A category value to use for the All Sites list.
+ */
+const ALL_SITES: string = 'all-sites';
+
+/**
+ * An invalid subtype value.
+ */
+export const INVALID_CATEGORY_SUBTYPE: string = '';
+
+/**
+ * Contains the possible record action types.
+ * This should be kept in sync with the |AllSitesAction2| enum in
+ * chrome/browser/ui/webui/settings/site_settings_handler.cc
+ */
+export enum AllSitesAction2 {
+  LOAD_PAGE = 0,
+  RESET_SITE_GROUP_PERMISSIONS = 1,
+  RESET_ORIGIN_PERMISSIONS = 2,
+  CLEAR_ALL_DATA = 3,
+  CLEAR_SITE_GROUP_DATA = 4,
+  CLEAR_ORIGIN_DATA = 5,
+  ENTER_SITE_DETAILS = 6,
+}
+
+/**
+ * Contains the possible sort methods.
+ */
+export enum SortMethod {
+  NAME = 'name',
+  MOST_VISITED = 'most-visited',
+  STORAGE = 'data-stored',
+}
+
+/**
+ * Contains types of dialogs on the AllSites page,
+ * used for logging userActions.
+ */
+export enum ALL_SITES_DIALOG {
+  CLEAR_DATA = 'ClearData',
+  RESET_PERMISSIONS = 'ResetPermissions',
+}
+
+/**
+ * String representation of the wildcard used for universal
+ * match for SiteExceptions.
+ */
+export const SITE_EXCEPTION_WILDCARD: string = '*';
diff --git a/chrome/browser/resources/settings/site_settings/cookie_info.js b/chrome/browser/resources/settings/site_settings/cookie_info.ts
similarity index 79%
rename from chrome/browser/resources/settings/site_settings/cookie_info.js
rename to chrome/browser/resources/settings/site_settings/cookie_info.ts
index c57c6e9..0a76df0 100644
--- a/chrome/browser/resources/settings/site_settings/cookie_info.js
+++ b/chrome/browser/resources/settings/site_settings/cookie_info.ts
@@ -6,21 +6,19 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 // clang-format on
 
-/**
- * @typedef {{hasChildren: boolean,
- *            id: string,
- *            idPath: string,
- *            title: string,
- *            totalUsage: string,
- *            type: string}}
- */
-export let CookieDetails;
+export type CookieDetails = {
+  hasChildren: boolean,
+  id: string,
+  idPath: string,
+  title: string,
+  totalUsage: string,
+  type: string,
+};
 
-/**
- * @typedef {{content: string,
- *            label: string}}
- */
-export let CookieDataForDisplay;
+export type CookieDataForDisplay = {
+  content: string,
+  label: string,
+};
 
 // This structure maps the various cookie type names from C++ (hence the
 // underscores) to arrays of the different types of data each has, along with
@@ -29,7 +27,7 @@
 // 1) to list what subset of the cookie data we want to show in the UI.
 // 2) What order to show it in.
 // 3) What user friendly label to prefix the data with.
-export const cookieInfo = {
+export const cookieInfo: {[key: string]: Array<Array<string>>} = {
   'cookie': [
     ['name', 'cookieName'], ['content', 'cookieContent'],
     ['domain', 'cookieDomain'], ['path', 'cookiePath'],
@@ -74,12 +72,11 @@
 
 /**
  * Get cookie data for a given HTML node.
- * @param {CookieDetails} data The contents of the cookie.
- * @return {!Array<CookieDataForDisplay>}
+ * @param data The contents of the cookie.
  */
-export const getCookieData = function(data) {
-  /** @type {!Array<CookieDataForDisplay>} */
-  const out = [];
+export function getCookieData(data: CookieDetails):
+    Array<CookieDataForDisplay> {
+  const out: Array<CookieDataForDisplay> = [];
   const fields = cookieInfo[data.type];
   for (let i = 0; i < fields.length; i++) {
     const field = fields[i];
@@ -87,13 +84,14 @@
     // and see if those keys are present in the data. If so, display them
     // (in the order determined by |cookieInfo|).
     const key = field[0];
-    if (data[key].length > 0) {
-      const entry = /** @type {CookieDataForDisplay} */ ({
+    const value = (data as unknown as {[key: string]: string})[key];
+    if (value.length > 0) {
+      const entry = {
         label: loadTimeData.getString(field[1]),
-        content: data[key],
-      });
+        content: value,
+      };
       out.push(entry);
     }
   }
   return out;
-};
+}
diff --git a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
deleted file mode 100644
index 7b80854..0000000
--- a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.js
+++ /dev/null
@@ -1,157 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A helper object used from the Cookies and Local Storage Data
- * section.
- */
-
-// clang-format off
-import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
-import {CookieDetails} from './cookie_info.js';
-// clang-format on
-
-/**
- * @typedef {{
- *   localData: string,
- *   site: string,
- * }}
- */
-export let LocalDataItem;
-
-/**
- * Number of cookies attached to a given domain / eTLD+1.
- * @typedef {{
- *   etldPlus1: string,
- *   numCookies: number,
- * }}
- */
-let EtldPlus1CookieNumber;
-
-/** @interface */
-export class LocalDataBrowserProxy {
-  /**
-   * @param {string} filter Search filter (use "" for none).
-   * @return {!Promise<!Array<!LocalDataItem>>}
-   */
-  getDisplayList(filter) {}
-
-  /**
-   * Removes all local data (local storage, cookies, etc.).
-   * Note: on-tree-item-removed will not be sent.
-   * @return {!Promise} To signal completion.
-   */
-  removeAll() {}
-
-  /**
-   * Remove items that pass the current filter. Completion signaled by
-   * on-tree-item-removed.
-   */
-  removeShownItems() {}
-
-  /**
-   * Remove data for a specific site. Completion signaled by
-   * on-tree-item-removed.
-   * @param {string} site Site to delete data for.
-   */
-  removeSite(site) {}
-
-  /**
-   * Gets the cookie details for a particular site.
-   * @param {string} site The name of the site.
-   * @return {!Promise<!Array<!CookieDetails>>}
-   */
-  getCookieDetails(site) {}
-
-  /**
-   * Gets the plural string for a given number of cookies.
-   * @param {number} numCookies The number of cookies.
-   * @return {!Promise<string>}
-   */
-  getNumCookiesString(numCookies) {}
-
-  /**
-   * Reloads all local data.
-   * TODO(dschuyler): rename function to reload().
-   * @return {!Promise} To signal completion.
-   */
-  reloadCookies() {}
-
-  /**
-   * Removes a given piece of site data.
-   * @param {string} path The path to the item in the tree model.
-   */
-  removeItem(path) {}
-
-  /**
-   * Removes all SameSite=None cookies, as well as storage available in
-   * third-party contexts.
-   * Note: on-tree-item-removed will not be sent.
-   * @return {!Promise} To signal completion.
-   */
-  removeAllThirdPartyCookies() {}
-}
-
-/**
- * @implements {LocalDataBrowserProxy}
- */
-export class LocalDataBrowserProxyImpl {
-  /** @override */
-  getDisplayList(filter) {
-    return sendWithPromise('localData.getDisplayList', filter);
-  }
-
-  /** @override */
-  removeAll() {
-    return sendWithPromise('localData.removeAll');
-  }
-
-  /** @override */
-  removeShownItems() {
-    chrome.send('localData.removeShownItems');
-  }
-
-  /** @override */
-  removeSite(site) {
-    chrome.send('localData.removeSite', [site]);
-  }
-
-  /** @override */
-  getCookieDetails(site) {
-    return sendWithPromise('localData.getCookieDetails', site);
-  }
-
-  /** @override */
-  getNumCookiesString(numCookies) {
-    return sendWithPromise('localData.getNumCookiesString', numCookies);
-  }
-
-  /** @override */
-  reloadCookies() {
-    return sendWithPromise('localData.reload');
-  }
-
-  /** @override */
-  removeItem(path) {
-    chrome.send('localData.removeItem', [path]);
-  }
-
-  /** @override */
-  removeAllThirdPartyCookies() {
-    return sendWithPromise('localData.removeThirdPartyCookies');
-  }
-
-  /** @return {!LocalDataBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new LocalDataBrowserProxyImpl());
-  }
-
-  /** @param {!LocalDataBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
-}
-
-/** @type {?LocalDataBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.ts b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.ts
new file mode 100644
index 0000000..bb5e59d
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/local_data_browser_proxy.ts
@@ -0,0 +1,126 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used from the Cookies and Local Storage Data
+ * section.
+ */
+
+// clang-format off
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+import {CookieDetails} from './cookie_info.js';
+// clang-format on
+
+export type LocalDataItem = {
+  localData: string,
+  site: string,
+};
+
+/**
+ * Number of cookies attached to a given domain / eTLD+1.
+ */
+type EtldPlus1CookieNumber = {
+  etldPlus1: string,
+  numCookies: number,
+};
+
+export interface LocalDataBrowserProxy {
+  getDisplayList(filter: string): Promise<Array<LocalDataItem>>;
+
+  /**
+   * Removes all local data (local storage, cookies, etc.).
+   * Note: on-tree-item-removed will not be sent.
+   */
+  removeAll(): Promise<void>;
+
+  /**
+   * Remove items that pass the current filter. Completion signaled by
+   * on-tree-item-removed.
+   */
+  removeShownItems(): void;
+
+  /**
+   * Remove data for a specific site. Completion signaled by
+   * on-tree-item-removed.
+   */
+  removeSite(site: string): void;
+
+  /**
+   * Gets the cookie details for a particular site.
+   */
+  getCookieDetails(site: string): Promise<Array<CookieDetails>>;
+
+  /**
+   * Gets the plural string for a given number of cookies.
+   * @param numCookies The number of cookies.
+   */
+  getNumCookiesString(numCookies: number): Promise<string>;
+
+  /**
+   * Reloads all local data.
+   * TODO(dschuyler): rename function to reload().
+   */
+  reloadCookies(): Promise<void>;
+
+  /**
+   * Removes a given piece of site data.
+   * @param path The path to the item in the tree model.
+   */
+  removeItem(path: string): void;
+
+  /**
+   * Removes all SameSite=None cookies, as well as storage available in
+   * third-party contexts.
+   * Note: on-tree-item-removed will not be sent.
+   */
+  removeAllThirdPartyCookies(): Promise<void>;
+}
+
+export class LocalDataBrowserProxyImpl implements LocalDataBrowserProxy {
+  getDisplayList(filter: string) {
+    return sendWithPromise('localData.getDisplayList', filter);
+  }
+
+  removeAll() {
+    return sendWithPromise('localData.removeAll');
+  }
+
+  removeShownItems() {
+    chrome.send('localData.removeShownItems');
+  }
+
+  removeSite(site: string) {
+    chrome.send('localData.removeSite', [site]);
+  }
+
+  getCookieDetails(site: string) {
+    return sendWithPromise('localData.getCookieDetails', site);
+  }
+
+  getNumCookiesString(numCookies: number) {
+    return sendWithPromise('localData.getNumCookiesString', numCookies);
+  }
+
+  reloadCookies() {
+    return sendWithPromise('localData.reload');
+  }
+
+  removeItem(path: string) {
+    chrome.send('localData.removeItem', [path]);
+  }
+
+  removeAllThirdPartyCookies() {
+    return sendWithPromise('localData.removeThirdPartyCookies');
+  }
+
+  static getInstance(): LocalDataBrowserProxy {
+    return instance || (instance = new LocalDataBrowserProxyImpl());
+  }
+
+  static setInstance(obj: LocalDataBrowserProxy) {
+    instance = obj;
+  }
+}
+
+let instance: LocalDataBrowserProxy|null = null;
diff --git a/chrome/browser/resources/settings/site_settings/site_data.js b/chrome/browser/resources/settings/site_settings/site_data.ts
similarity index 73%
rename from chrome/browser/resources/settings/site_settings/site_data.js
rename to chrome/browser/resources/settings/site_settings/site_data.ts
index 910dc0f3..bebd065a 100644
--- a/chrome/browser/resources/settings/site_settings/site_data.js
+++ b/chrome/browser/resources/settings/site_settings/site_data.ts
@@ -18,10 +18,11 @@
 import '../settings_shared_css.js';
 import './site_data_entry.js';
 
+import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js';
-import {ListPropertyUpdateBehavior, ListPropertyUpdateBehaviorInterface} from 'chrome://resources/js/list_property_update_behavior.m.js';
-import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
+import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js';
+import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, microTask, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {BaseMixin, BaseMixinInterface} from '../base_mixin.js';
@@ -29,31 +30,38 @@
 import {loadTimeData} from '../i18n_setup.js';
 import {MetricsBrowserProxyImpl, PrivacyElementInteractions} from '../metrics_browser_proxy.js';
 import {routes} from '../route.js';
-import {Route, RouteObserverBehavior, Router} from '../router.js';
+import {Route, RouteObserverMixinInterface, Router} from '../router.js';
 
 import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl, LocalDataItem} from './local_data_browser_proxy.js';
 
-/**
- * @typedef {{
- *   id: string,
- *   start: number,
- *   count: number,
- * }}
- */
-let CookieRemovePacket;
+type FocusConfig = Map<string, string|(() => void)>;
 
-/**
- * @constructor
- * @extends {PolymerElement}
- * @implements {ListPropertyUpdateBehaviorInterface}
- * @implements {BaseMixinInterface}
- * @implements {WebUIListenerBehaviorInterface}
- */
-const SiteDataElementBase = mixinBehaviors(
-    [ListPropertyUpdateBehavior, WebUIListenerBehavior],
-    GlobalScrollTargetMixin(BaseMixin(PolymerElement)));
+type SelectedItem = {
+  item: LocalDataItem,
+  index: number,
+};
 
-/** @polymer */
+type RepeaterEvent = {
+  model: SelectedItem,
+};
+
+interface SiteDataElement {
+  $: {
+    confirmDeleteDialog: CrDialogElement,
+    confirmDeleteThirdPartyDialog: CrDialogElement,
+    removeShowingSites: HTMLElement,
+    removeAllThirdPartyCookies: HTMLElement,
+  };
+}
+
+const SiteDataElementBase =
+    mixinBehaviors(
+        [ListPropertyUpdateBehavior, WebUIListenerBehavior],
+        GlobalScrollTargetMixin(BaseMixin(PolymerElement))) as {
+      new (): PolymerElement & ListPropertyUpdateBehavior & BaseMixinInterface &
+      WebUIListenerBehavior & RouteObserverMixinInterface
+    };
+
 class SiteDataElement extends SiteDataElementBase {
   static get is() {
     return 'site-data';
@@ -74,7 +82,6 @@
         type: String,
       },
 
-      /** @type {!Map<string, (string|Function)>} */
       focusConfig: {
         type: Object,
         observer: 'focusConfigChanged_',
@@ -82,7 +89,6 @@
 
       isLoading_: Boolean,
 
-      /** @type {!Array<!LocalDataItem>} */
       sites: {
         type: Array,
         value() {
@@ -92,53 +98,50 @@
 
       /**
        * GlobalScrollTargetMixin
-       * @override
        */
       subpageRoute: {
         type: Object,
         value: routes.SITE_SETTINGS_SITE_DATA,
       },
 
-      /** @private */
       lastFocused_: Object,
-
-      /** @private */
       listBlurred_: Boolean,
     };
   }
 
+  filter: string;
+  focusConfig: FocusConfig;
+  private isLoading_: boolean;
+  sites: Array<LocalDataItem>;
+  subpageRoute: Route;
+  private listBlurred_: boolean;
+  private browserProxy_: LocalDataBrowserProxy =
+      LocalDataBrowserProxyImpl.getInstance();
+  private lastSelected_: SelectedItem|null;
+
   constructor() {
     super();
 
-    /** @private {!LocalDataBrowserProxy} */
-    this.browserProxy_ = LocalDataBrowserProxyImpl.getInstance();
-
     /**
      * When navigating to site data details sub-page, |lastSelected_| holds the
      * site name as well as the index of the selected site. This is used when
      * navigating back to site data in order to focus on the correct site.
-     * @private {!{item: !LocalDataItem, index: number}|null}
      */
     this.lastSelected_ = null;
   }
 
-  /** @override */
   ready() {
     super.ready();
 
-    this.addWebUIListener(
-        'on-tree-item-removed', this.updateSiteList_.bind(this));
+    this.addWebUIListener('on-tree-item-removed', () => this.updateSiteList_());
   }
 
   /**
    * Reload cookies when the site data page is visited.
    *
    * RouteObserverBehavior
-   * @param {!Route} currentRoute
-   * @param {!Route} previousRoute
-   * @protected
    */
-  currentRouteChanged(currentRoute, previousRoute) {
+  currentRouteChanged(currentRoute: Route, previousRoute: Route) {
     super.currentRouteChanged(currentRoute);
     // Reload cookies on navigation to the site data page from a different
     // page. Avoid reloading on repeated navigations to the same page, as these
@@ -149,18 +152,13 @@
       // Needed to fix iron-list rendering issue. The list will not render
       // correctly until a scroll occurs.
       // See https://crbug.com/853906.
-      const ironList = /** @type {!IronListElement} */ (this.$$('iron-list'));
+      const ironList = this.shadowRoot!.querySelector('iron-list')!;
       ironList.scrollToIndex(0);
-      this.browserProxy_.reloadCookies().then(this.updateSiteList_.bind(this));
+      this.browserProxy_.reloadCookies().then(() => this.updateSiteList_());
     }
   }
 
-  /**
-   * @param {!Map<string, (string|Function)>} newConfig
-   * @param {?Map<string, (string|Function)>} oldConfig
-   * @private
-   */
-  focusConfigChanged_(newConfig, oldConfig) {
+  private focusConfigChanged_(_newConfig: FocusConfig, oldConfig: FocusConfig) {
     // focusConfig is set only once on the parent, so this observer should only
     // fire once.
     assert(!oldConfig);
@@ -195,25 +193,17 @@
     }
   }
 
-  /**
-   * @param {number} index
-   * @private
-   */
-  focusOnSiteSelectButton_(index) {
-    const ironList =
-        /** @type {!IronListElement} */ (this.$$('iron-list'));
+  private focusOnSiteSelectButton_(index: number) {
+    const ironList = this.shadowRoot!.querySelector('iron-list')!;
     ironList.focusItem(index);
     const siteToSelect = this.sites[index].site.replace(/[.]/g, '\\.');
-    const button = this.$$(`#siteItem_${siteToSelect}`).$$('.subpage-arrow');
+    const button =
+        this.$$(`#siteItem_${siteToSelect}`)!.shadowRoot!.querySelector(
+            '.subpage-arrow')!;
     focusWithoutInk(assert(button));
   }
 
-  /**
-   * @param {string} current
-   * @param {string|undefined} previous
-   * @private
-   */
-  onFilterChanged_(current, previous) {
+  private onFilterChanged_(_current: string, previous?: string) {
     // Ignore filter changes which do not occur on the site data page. The
     // site settings data details subpage expects the tree model to remain in
     // the same state.
@@ -227,9 +217,8 @@
 
   /**
    * Gather all the site data.
-   * @private
    */
-  updateSiteList_() {
+  private updateSiteList_() {
     this.isLoading_ = true;
     this.browserProxy_.getDisplayList(this.filter).then(localDataItems => {
       this.updateList('sites', item => item.site, localDataItems);
@@ -240,43 +229,35 @@
 
   /**
    * Returns the string to use for the Remove label.
-   * @param {string} filter The current filter string.
-   * @return {string}
-   * @private
+   * @param filter The current filter string.
    */
-  computeRemoveLabel_(filter) {
+  private computeRemoveLabel_(filter: string): string {
     if (filter.length === 0) {
       return loadTimeData.getString('siteSettingsCookieRemoveAll');
     }
     return loadTimeData.getString('siteSettingsCookieRemoveAllShown');
   }
 
-  /** @private */
-  onCloseDialog_() {
+  private onCloseDialog_() {
     this.$.confirmDeleteDialog.close();
   }
 
-  /** @private */
-  onCloseThirdPartyDialog_() {
+  private onCloseThirdPartyDialog_() {
     this.$.confirmDeleteThirdPartyDialog.close();
   }
 
-  /** @private */
-  onConfirmDeleteDialogClosed_() {
+  private onConfirmDeleteDialogClosed_() {
     focusWithoutInk(assert(this.$.removeShowingSites));
   }
 
-  /** @private */
-  onConfirmDeleteThirdPartyDialogClosed_() {
+  private onConfirmDeleteThirdPartyDialogClosed_() {
     focusWithoutInk(assert(this.$.removeAllThirdPartyCookies));
   }
 
   /**
    * Shows a dialog to confirm the deletion of multiple sites.
-   * @param {!Event} e
-   * @private
    */
-  onRemoveShowingSitesTap_(e) {
+  onRemoveShowingSitesTap_(e: Event) {
     e.preventDefault();
     this.$.confirmDeleteDialog.showModal();
   }
@@ -284,18 +265,16 @@
   /**
    * Shows a dialog to confirm the deletion of cookies available
    * in third-party contexts and associated site data.
-   * @private
    */
-  onRemoveThirdPartyCookiesTap_(e) {
+  private onRemoveThirdPartyCookiesTap_(e: Event) {
     e.preventDefault();
     this.$.confirmDeleteThirdPartyDialog.showModal();
   }
 
   /**
    * Called when deletion for all showing sites has been confirmed.
-   * @private
    */
-  onConfirmDelete_() {
+  private onConfirmDelete_() {
     this.$.confirmDeleteDialog.close();
     if (this.filter.length === 0) {
       MetricsBrowserProxyImpl.getInstance().recordSettingsPageHistogram(
@@ -315,20 +294,15 @@
   /**
    * Called when deletion of all third-party cookies and site data has been
    * confirmed.
-   * @private
    */
-  onConfirmThirdPartyDelete_() {
+  private onConfirmThirdPartyDelete_() {
     this.$.confirmDeleteThirdPartyDialog.close();
     this.browserProxy_.removeAllThirdPartyCookies().then(() => {
       this.updateSiteList_();
     });
   }
 
-  /**
-   * @param {!{model: !{item: !LocalDataItem, index: number}}} event
-   * @private
-   */
-  onSiteClick_(event) {
+  private onSiteClick_(event: RepeaterEvent) {
     // If any delete button is selected, the focus will be in a bad state when
     // returning to this page. To avoid this, the site select button is given
     // focus. See https://crbug.com/872197.
@@ -339,11 +313,7 @@
     this.lastSelected_ = event.model;
   }
 
-  /**
-   * @private
-   * @return {boolean}
-   */
-  showRemoveThirdPartyCookies_() {
+  private showRemoveThirdPartyCookies_(): boolean {
     return loadTimeData.getBoolean('enableRemovingAllThirdPartyCookies') &&
         this.sites.length > 0 && this.filter.length === 0;
   }
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.js b/chrome/browser/resources/settings/site_settings/site_data_entry.ts
similarity index 91%
rename from chrome/browser/resources/settings/site_settings/site_data_entry.js
rename to chrome/browser/resources/settings/site_settings/site_data_entry.ts
index af02e32..fb7d36a 100644
--- a/chrome/browser/resources/settings/site_settings/site_data_entry.js
+++ b/chrome/browser/resources/settings/site_settings/site_data_entry.ts
@@ -23,14 +23,10 @@
 
 import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl, LocalDataItem} from './local_data_browser_proxy.js';
 
-/**
- * @constructor
- * @extends {PolymerElement}
- */
 const SiteDataEntryElementBase =
-    mixinBehaviors([FocusRowBehavior, I18nBehavior], PolymerElement);
+    mixinBehaviors([FocusRowBehavior, I18nBehavior], PolymerElement) as
+    {new (): PolymerElement & I18nBehavior};
 
-/** @polymer */
 class SiteDataEntryElement extends SiteDataEntryElementBase {
   static get is() {
     return 'site-data-entry';
@@ -42,17 +38,16 @@
 
   static get properties() {
     return {
-      /** @type {!LocalDataItem} */
       model: Object,
     };
   }
 
+  model: LocalDataItem;
+
   /**
    * Deletes all site data for this site.
-   * @param {!Event} e
-   * @private
    */
-  onRemove_(e) {
+  private onRemove_(e: Event) {
     e.stopPropagation();
     MetricsBrowserProxyImpl.getInstance().recordSettingsPageHistogram(
         PrivacyElementInteractions.SITE_DATA_REMOVE_SITE);
diff --git a/chrome/browser/resources/settings/site_settings/site_details.ts b/chrome/browser/resources/settings/site_settings/site_details.ts
index 8b1d86d8..23bb490 100644
--- a/chrome/browser/resources/settings/site_settings/site_details.ts
+++ b/chrome/browser/resources/settings/site_settings/site_details.ts
@@ -50,7 +50,7 @@
 const SiteDetailsElementBase =
     mixinBehaviors(
         [I18nBehavior, WebUIListenerBehavior],
-        SiteSettingsMixin(RouteObserverMixin(PolymerElement))) as {
+        RouteObserverMixin(SiteSettingsMixin(PolymerElement))) as {
       new (): PolymerElement & I18nBehavior & WebUIListenerBehavior &
       SiteSettingsMixinInterface & RouteObserverMixinInterface
     };
@@ -168,7 +168,7 @@
       if (!valid) {
         Router.getInstance().navigateToPreviousRoute();
       } else {
-        this.fetchingForHost_ = this.toUrl(this.origin_).hostname;
+        this.fetchingForHost_ = this.toUrl(this.origin_)!.hostname;
         this.storedData_ = '';
         this.websiteUsageProxy_.fetchUsageTotal(this.fetchingForHost_);
         this.browserProxy.getCategoryList(this.origin_).then((categoryList) => {
@@ -289,7 +289,7 @@
     MetricsBrowserProxyImpl.getInstance().recordSettingsPageHistogram(
         PrivacyElementInteractions.SITE_DETAILS_CLEAR_DATA);
     if (this.hasUsage_(this.storedData_, this.numCookies_)) {
-      this.websiteUsageProxy_.clearUsage(this.toUrl(this.origin_).href);
+      this.websiteUsageProxy_.clearUsage(this.toUrl(this.origin_)!.href);
       this.storedData_ = '';
       this.numCookies_ = '';
     }
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.html b/chrome/browser/resources/settings/site_settings/site_details_permission.html
index 26f2632..a910736 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.html
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.html
@@ -41,23 +41,23 @@
             on-change="onPermissionSelectionChange_"
             disabled$="[[!isPermissionUserControlled_(site.source, category,
                                                       site.setting)]]">
-          <option id="default" value$="[[ContentSetting.DEFAULT]]">
+          <option id="default" value$="[[contentSettingEnum_.DEFAULT]]">
             [[defaultSettingString_(
                 defaultSetting_,
                 category,
                 useAutomaticLabel)]]
           </option>
-          <option id="allow" value$="[[ContentSetting.ALLOW]]"
+          <option id="allow" value$="[[contentSettingEnum_.ALLOW]]"
               hidden$="[[!showAllowedSetting_(category)]]">
             $i18n{siteSettingsActionAllow}
           </option>
-          <option id="block" value$="[[ContentSetting.BLOCK]]">
+          <option id="block" value$="[[contentSettingEnum_.BLOCK]]">
             [[blockSettingString_(
                 category,
                 '$i18n{siteSettingsActionBlock}',
                 '$i18n{siteSettingsActionMute}')]]
           </option>
-          <option id="ask" value$="[[ContentSetting.ASK]]"
+          <option id="ask" value$="[[contentSettingEnum_.ASK]]"
               hidden$="[[!showAskSetting_(category, site.setting,
                                           site.source)]]">
             $i18n{siteSettingsActionAsk}
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.ts b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
index 0099362..be3b2f2 100644
--- a/chrome/browser/resources/settings/site_settings/site_details_permission.ts
+++ b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
@@ -73,6 +73,13 @@
 
       icon: String,
 
+      /**
+       * Expose ContentSetting enum to HTML bindings.
+       */
+      contentSettingEnum_: {
+        type: Object,
+        value: ContentSetting,
+      },
     };
   }
 
@@ -147,7 +154,8 @@
    */
   private onPermissionSelectionChange_() {
     this.browserProxy.setOriginPermissions(
-        this.site.origin, this.category, this.$.permission.value);
+        this.site.origin, this.category,
+        this.$.permission.value as ContentSetting);
   }
 
   /**
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.ts b/chrome/browser/resources/settings/site_settings/site_entry.ts
index 5acef46..a6c3cf1c 100644
--- a/chrome/browser/resources/settings/site_settings/site_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/site_entry.ts
@@ -52,7 +52,7 @@
 
 const SiteEntryElementBase =
     mixinBehaviors(
-        [FocusRowBehavior], SiteSettingsMixin(BaseMixin(PolymerElement))) as
+        [FocusRowBehavior], BaseMixin(SiteSettingsMixin(PolymerElement))) as
     {new (): PolymerElement & SiteSettingsMixinInterface & BaseMixinInterface};
 
 class SiteEntryElement extends SiteEntryElementBase {
@@ -243,7 +243,7 @@
    * @return The scheme if non-HTTPS, or empty string if HTTPS.
    */
   private originScheme_(origin: OriginInfo): string {
-    const url = this.toUrl(origin.origin);
+    const url = this.toUrl(origin.origin)!;
     const scheme = url.protocol.replace(new RegExp(':*$'), '');
     const HTTPS_SCHEME = 'https';
     if (scheme === HTTPS_SCHEME) {
@@ -269,7 +269,8 @@
     // origin. Otherwise find the origin with largest storage, and use the
     // number of cookies as a tie breaker.
     for (const originInfo of origins) {
-      if (this.toUrl(originInfo.origin).host === 'www.' + siteGroup.etldPlus1) {
+      if (this.toUrl(originInfo.origin)!.host ===
+          'www.' + siteGroup.etldPlus1) {
         return originInfo.origin;
       }
     }
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.ts b/chrome/browser/resources/settings/site_settings/site_list_entry.ts
index 36271f3..ec40c53 100644
--- a/chrome/browser/resources/settings/site_settings/site_list_entry.ts
+++ b/chrome/browser/resources/settings/site_settings/site_list_entry.ts
@@ -36,7 +36,7 @@
 
 const SiteListEntryElementBase =
     mixinBehaviors(
-        [FocusRowBehavior], SiteSettingsMixin(BaseMixin(PolymerElement))) as
+        [FocusRowBehavior], BaseMixin(SiteSettingsMixin(PolymerElement))) as
     {new (): PolymerElement & BaseMixinInterface & SiteSettingsMixinInterface};
 
 class SiteListEntryElement extends SiteListEntryElementBase {
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_mixin.js b/chrome/browser/resources/settings/site_settings/site_settings_mixin.js
deleted file mode 100644
index 97881bb..0000000
--- a/chrome/browser/resources/settings/site_settings/site_settings_mixin.js
+++ /dev/null
@@ -1,228 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview Behavior common to Site Settings classes.
- */
-
-// clang-format off
-import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {dedupingMixin} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {ContentSetting,ContentSettingsTypes, SiteSettingSource} from './constants.js';
-import {RawSiteException,SiteException,SiteSettingsPrefsBrowserProxy,SiteSettingsPrefsBrowserProxyImpl} from './site_settings_prefs_browser_proxy.js';
-// clang-format on
-
-/**
- * @polymer
- * @mixinFunction
- */
-export const SiteSettingsMixin = dedupingMixin(superClass => {
-  /**
-   * @polymer
-   * @mixinClass
-   */
-  class SiteSettingsMixin extends superClass {
-    static get properties() {
-      return {
-        /**
-         * The string ID of the category this element is displaying data for.
-         * See site_settings/constants.js for possible values.
-         * @type {!ContentSettingsTypes}
-         */
-        category: String,
-
-        /**
-         * A cached list of ContentSettingsTypes with a standard allow-block-ask
-         * pattern that are currently enabled for use. This property is the same
-         * across all elements with SiteSettingsMixin ('static').
-         * @type {Array<ContentSettingsTypes>}
-         * @private
-         */
-        contentTypes_: {
-          type: Array,
-          value: [],
-        },
-      };
-    }
-
-    constructor() {
-      super();
-
-      /**
-       * The browser proxy used to retrieve and change information about site
-       * settings categories and the sites within.
-       * @type {SiteSettingsPrefsBrowserProxy}
-       */
-      this.browserProxy = SiteSettingsPrefsBrowserProxyImpl.getInstance();
-    }
-
-    /** @override */
-    ready() {
-      super.ready();
-
-      this.ContentSetting = ContentSetting;
-    }
-
-    /**
-     * Ensures the URL has a scheme (assumes http if omitted).
-     * @param {string} url The URL with or without a scheme.
-     * @return {string} The URL with a scheme, or an empty string.
-     */
-    ensureUrlHasScheme(url) {
-      if (url.length === 0) {
-        return url;
-      }
-      return url.includes('://') ? url : 'http://' + url;
-    }
-
-    /**
-     * Removes redundant ports, such as port 80 for http and 443 for https.
-     * @param {string} url The URL to sanitize.
-     * @return {string} The URL without redundant ports, if any.
-     */
-    sanitizePort(url) {
-      const urlWithScheme = this.ensureUrlHasScheme(url);
-      if (urlWithScheme.startsWith('https://') &&
-          urlWithScheme.endsWith(':443')) {
-        return url.slice(0, -4);
-      }
-      if (urlWithScheme.startsWith('http://') &&
-          urlWithScheme.endsWith(':80')) {
-        return url.slice(0, -3);
-      }
-      return url;
-    }
-
-    /**
-     * Returns true if the passed content setting is considered 'enabled'.
-     * @param {string} setting
-     * @return {boolean}
-     * @protected
-     */
-    computeIsSettingEnabled(setting) {
-      return setting !== ContentSetting.BLOCK;
-    }
-
-    /**
-     * Converts a string origin/pattern to a URL.
-     * @param {string} originOrPattern The origin/pattern to convert to URL.
-     * @return {URL} The URL to return (or null if origin is not a valid URL).
-     * @protected
-     */
-    toUrl(originOrPattern) {
-      if (originOrPattern.length === 0) {
-        return null;
-      }
-      // TODO(finnur): Hmm, it would probably be better to ensure scheme on the
-      //     JS/C++ boundary.
-      // TODO(dschuyler): I agree. This filtering should be done in one go,
-      // rather that during the sort. The URL generation should be wrapped in a
-      // try/catch as well.
-      originOrPattern = originOrPattern.replace('*://', '');
-      originOrPattern = originOrPattern.replace('[*.]', '');
-      return new URL(this.ensureUrlHasScheme(originOrPattern));
-    }
-
-    /**
-     * Returns a user-friendly name for the origin.
-     * @param {string} origin
-     * @return {string} The user-friendly name.
-     * @protected
-     */
-    originRepresentation(origin) {
-      try {
-        const url = this.toUrl(origin);
-        return url ? (url.host || url.origin) : '';
-      } catch (error) {
-        return '';
-      }
-    }
-
-    /**
-     * Convert an exception (received from the C++ handler) to a full
-     * SiteException.
-     * @param {!RawSiteException} exception The raw site exception from C++.
-     * @return {!SiteException} The expanded (full) SiteException.
-     * @protected
-     */
-    expandSiteException(exception) {
-      const origin = exception.origin;
-      const embeddingOrigin = exception.embeddingOrigin;
-
-      // TODO(patricialor): |exception.source| should be one of the values
-      // defined in |SiteSettingSource|.
-      let enforcement =
-          /** @type {?chrome.settingsPrivate.Enforcement} */ (null);
-      if (exception.source === SiteSettingSource.EXTENSION ||
-          exception.source === SiteSettingSource.HOSTED_APP ||
-          exception.source === SiteSettingSource.POLICY) {
-        enforcement = chrome.settingsPrivate.Enforcement.ENFORCED;
-      }
-
-      let controlledBy = chrome.settingsPrivate.ControlledBy.PRIMARY_USER;
-      if (exception.source === SiteSettingSource.EXTENSION ||
-          exception.source === SiteSettingSource.HOSTED_APP) {
-        controlledBy = chrome.settingsPrivate.ControlledBy.EXTENSION;
-      } else if (exception.source === SiteSettingSource.POLICY) {
-        controlledBy = chrome.settingsPrivate.ControlledBy.USER_POLICY;
-      }
-
-      return {
-        category: this.category,
-        embeddingOrigin: embeddingOrigin,
-        incognito: exception.incognito,
-        isEmbargoed: exception.isEmbargoed,
-        origin: origin,
-        displayName: exception.displayName,
-        setting: exception.setting,
-        settingDetail: exception.settingDetail,
-        enforcement: enforcement,
-        controlledBy: controlledBy,
-      };
-    }
-  }
-
-  return SiteSettingsMixin;
-});
-
-/** @interface */
-export class SiteSettingsMixinInterface {
-  constructor() {
-    /** @type {SiteSettingsPrefsBrowserProxy} */
-    this.browserProxy;
-
-    /** @type {!ContentSettingsTypes} */
-    this.category;
-  }
-
-  /**
-   * @param {string} setting
-   * @return {boolean}
-   */
-  computeIsSettingEnabled(setting) {}
-
-  /**
-   * @param {string} origin
-   * @return {string}
-   */
-  originRepresentation(origin) {}
-
-  /**
-   * @param {string} originOrPattern
-   * @return {URL}
-   */
-  toUrl(originOrPattern) {}
-
-  /**
-   * @param {!RawSiteException} exception
-   * @return {!SiteException}
-   */
-  expandSiteException(exception) {}
-
-  /**
-   * @param {string} url
-   * @return {string}
-   */
-  sanitizePort(url) {}
-}
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts b/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts
new file mode 100644
index 0000000..bd0d711
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/site_settings_mixin.ts
@@ -0,0 +1,178 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview Behavior common to Site Settings classes.
+ */
+
+// clang-format off
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {dedupingMixin, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {ContentSetting,ContentSettingsTypes, SiteSettingSource} from './constants.js';
+import {RawSiteException,SiteException,SiteSettingsPrefsBrowserProxy,SiteSettingsPrefsBrowserProxyImpl} from './site_settings_prefs_browser_proxy.js';
+// clang-format on
+
+type Constructor<T> = new (...args: any[]) => T;
+
+export const SiteSettingsMixin = dedupingMixin(
+    <T extends Constructor<PolymerElement>>(superClass: T): T&
+    Constructor<SiteSettingsMixinInterface> => {
+      class SiteSettingsMixin extends superClass {
+        static get properties() {
+          return {
+            /**
+             * The string ID of the category this element is displaying data
+             * for. See site_settings/constants.js for possible values.
+             */
+            category: String,
+
+            /**
+             * A cached list of ContentSettingsTypes with a standard
+             * allow-block-ask pattern that are currently enabled for use. This
+             * property is the same across all elements with SiteSettingsMixin
+             * ('static').
+             */
+            contentTypes_: {
+              type: Array,
+              value: [],
+            },
+          };
+        }
+
+        category: ContentSettingsTypes;
+        private contentTypes_: Array<ContentSettingsTypes>;
+        browserProxy: SiteSettingsPrefsBrowserProxy;
+
+        constructor(...args: any[]) {
+          super(...args);
+
+          /**
+           * The browser proxy used to retrieve and change information about
+           * site settings categories and the sites within.
+           */
+          this.browserProxy = SiteSettingsPrefsBrowserProxyImpl.getInstance();
+        }
+
+        /**
+         * Ensures the URL has a scheme (assumes http if omitted).
+         * @param url The URL with or without a scheme.
+         * @return The URL with a scheme, or an empty string.
+         */
+        ensureUrlHasScheme(url: string): string {
+          if (url.length === 0) {
+            return url;
+          }
+          return url.includes('://') ? url : 'http://' + url;
+        }
+
+        /**
+         * Removes redundant ports, such as port 80 for http and 443 for https.
+         * @param url The URL to sanitize.
+         * @return The URL without redundant ports, if any.
+         */
+        sanitizePort(url: string): string {
+          const urlWithScheme = this.ensureUrlHasScheme(url);
+          if (urlWithScheme.startsWith('https://') &&
+              urlWithScheme.endsWith(':443')) {
+            return url.slice(0, -4);
+          }
+          if (urlWithScheme.startsWith('http://') &&
+              urlWithScheme.endsWith(':80')) {
+            return url.slice(0, -3);
+          }
+          return url;
+        }
+
+        /**
+         * @return true if the passed content setting is considered 'enabled'.
+         */
+        computeIsSettingEnabled(setting: ContentSetting): boolean {
+          return setting !== ContentSetting.BLOCK;
+        }
+
+        /**
+         * Converts a string origin/pattern to a URL.
+         * @param originOrPattern The origin/pattern to convert to URL.
+         * @return The URL to return (or null if origin is not a valid URL).
+         */
+        toUrl(originOrPattern: string): URL|null {
+          if (originOrPattern.length === 0) {
+            return null;
+          }
+          // TODO(finnur): Hmm, it would probably be better to ensure scheme on
+          // the JS/C++ boundary.
+          // TODO(dschuyler): I agree. This filtering should be done in one go,
+          // rather that during the sort. The URL generation should be wrapped
+          // in a try/catch as well.
+          originOrPattern = originOrPattern.replace('*://', '');
+          originOrPattern = originOrPattern.replace('[*.]', '');
+          return new URL(this.ensureUrlHasScheme(originOrPattern));
+        }
+
+        /**
+         * @return a user-friendly name for the origin.
+         */
+        originRepresentation(origin: string): string {
+          try {
+            const url = this.toUrl(origin);
+            return url ? (url.host || url.origin) : '';
+          } catch (error) {
+            return '';
+          }
+        }
+
+        /**
+         * Convert an exception (received from the C++ handler) to a full
+         * SiteException.
+         * @param exception The raw site exception from C++.
+         * @return The expanded (full) SiteException.
+         */
+        expandSiteException(exception: RawSiteException): SiteException {
+          const origin = exception.origin;
+          const embeddingOrigin = exception.embeddingOrigin;
+
+          // TODO(patricialor): |exception.source| should be one of the values
+          // defined in |SiteSettingSource|.
+          let enforcement = null;
+          if (exception.source === SiteSettingSource.EXTENSION ||
+              exception.source === SiteSettingSource.HOSTED_APP ||
+              exception.source === SiteSettingSource.POLICY) {
+            enforcement = chrome.settingsPrivate.Enforcement.ENFORCED;
+          }
+
+          let controlledBy = chrome.settingsPrivate.ControlledBy.PRIMARY_USER;
+          if (exception.source === SiteSettingSource.EXTENSION ||
+              exception.source === SiteSettingSource.HOSTED_APP) {
+            controlledBy = chrome.settingsPrivate.ControlledBy.EXTENSION;
+          } else if (exception.source === SiteSettingSource.POLICY) {
+            controlledBy = chrome.settingsPrivate.ControlledBy.USER_POLICY;
+          }
+
+          return {
+            category: this.category,
+            embeddingOrigin: embeddingOrigin,
+            incognito: exception.incognito,
+            isEmbargoed: exception.isEmbargoed,
+            origin: origin,
+            displayName: exception.displayName,
+            setting: exception.setting,
+            settingDetail: exception.settingDetail,
+            enforcement: enforcement,
+            controlledBy: controlledBy,
+          };
+        }
+      }
+
+      return SiteSettingsMixin;
+    });
+
+export interface SiteSettingsMixinInterface {
+  browserProxy: SiteSettingsPrefsBrowserProxy;
+  category: ContentSettingsTypes;
+  computeIsSettingEnabled(setting: string): boolean;
+  originRepresentation(origin: string): string;
+  toUrl(originOrPattern: string): URL|null;
+  expandSiteException(exception: RawSiteException): SiteException;
+  sanitizePort(url: string): string;
+}
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
deleted file mode 100644
index 6e89ebd7..0000000
--- a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.js
+++ /dev/null
@@ -1,580 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-/**
- * @fileoverview A helper object used from the "Site Settings" section to
- * interact with the content settings prefs.
- */
-
-// clang-format off
-import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
-
-import {ChooserType,ContentSetting,ContentSettingsTypes,SiteSettingSource} from './constants.js';
-// clang-format on
-
-/**
- * The handler will send a policy source that is similar, but not exactly the
- * same as a ControlledBy value. If the ContentSettingProvider is omitted it
- * should be treated as 'default'.
- * @enum {string}
- */
-export const ContentSettingProvider = {
-  POLICY: 'policy',
-  SUPERVISED_USER: 'supervised_user',
-  EXTENSION: 'extension',
-  INSTALLED_WEBAPP_PROVIDER: 'installed_webapp_provider',
-  NOTIFICATION_ANDROID: 'notification_android',
-  EPHEMERAL: 'ephemeral',
-  PREFERENCE: 'preference',
-  DEFAULT: 'default',
-  TESTS: 'tests',
-  TESTS_OTHER: 'tests_other'
-};
-
-/**
- * Stores information about if a content setting is valid, and why.
- * @typedef {{isValid: boolean,
- *            reason: ?string}}
- */
-let IsValid;
-
-/**
- * Stores origin information. The |hasPermissionSettings| will be set to true
- * when this origin has permissions or when there is a pattern permission
- * affecting this origin.
- * @typedef {{origin: string,
- *            engagement: number,
- *            usage: number,
-              numCookies: number,
-              hasPermissionSettings: boolean,
-              isInstalled: boolean}}
- */
-export let OriginInfo;
-
-/**
- * Represents a list of sites, grouped under the same eTLD+1. For example, an
- * origin "https://www.example.com" would be grouped together with
- * "https://login.example.com" and "http://example.com" under a common eTLD+1 of
- * "example.com".
- * @typedef {{etldPlus1: string,
- *            numCookies: number,
- *            origins: Array<OriginInfo>,
- *            hasInstalledPWA: boolean}}
- */
-export let SiteGroup;
-
-/**
- * The site exception information passed from the C++ handler.
- * See also: SiteException.
- * @typedef {{embeddingOrigin: string,
- *            incognito: boolean,
- *            isEmbargoed: boolean,
- *            origin: string,
- *            displayName: string,
- *            settingDetail: ?string,
- *            type: string,
- *            setting: !ContentSetting,
- *            source: !SiteSettingSource}}
- */
-export let RawSiteException;
-
-/**
- * The site exception after it has been converted/filtered for UI use.
- * See also: RawSiteException.
- * @typedef {{category: !ContentSettingsTypes,
- *            embeddingOrigin: string,
- *            incognito: boolean,
- *            isEmbargoed: boolean,
- *            origin: string,
- *            displayName: string,
- *            settingDetail: ?string,
- *            setting: !ContentSetting,
- *            enforcement: ?chrome.settingsPrivate.Enforcement,
- *            controlledBy: !chrome.settingsPrivate.ControlledBy,
- *            showAndroidSmsNote: (boolean|undefined)}}
- */
-export let SiteException;
-
-/**
- * Represents a list of exceptions recently configured for a site, where recent
- * is defined by the maximum number of sources parameter passed to
- * GetRecentSitePermissions.
- * @typedef {{origin: !string,
- *            incognito: boolean,
- *            recentPermissions: !Array<!RawSiteException>}}
- */
-export let RecentSitePermissions;
-
-/**
- * The chooser exception information passed from the C++ handler.
- * See also: ChooserException.
- * @typedef {{chooserType: !ChooserType,
- *            displayName: string,
- *            object: Object,
- *            sites: Array<!RawSiteException>}}
- */
-export let RawChooserException;
-
-/**
- * The chooser exception after it has been converted/filtered for UI use.
- * See also: RawChooserException.
- * @typedef {{chooserType: !ChooserType,
- *            displayName: string,
- *            object: Object,
- *            sites: Array<!SiteException>}}
- */
-export let ChooserException;
-
-/**
- * @typedef {{setting: !ContentSetting,
- *            source: !ContentSettingProvider}}
- */
-export let DefaultContentSetting;
-
-/**
- * @typedef {{name: string,
- *            id: string}}
- */
-export let MediaPickerEntry;
-
-/**
- * @typedef {{protocol: string,
- *            spec: string}}
- */
-let ProtocolHandlerEntry;
-
-/**
- * @typedef {{origin: string,
- *            setting: string,
- *            source: string,
- *            zoom: string}}
- */
-export let ZoomLevelEntry;
-
-/** @interface */
-export class SiteSettingsPrefsBrowserProxy {
-  /**
-   * Sets the default value for a site settings category.
-   * @param {string} contentType The name of the category to change.
-   * @param {string} defaultValue The name of the value to set as default.
-   */
-  setDefaultValueForContentType(contentType, defaultValue) {}
-
-  /**
-   * Gets the default value for a site settings category.
-   * @param {!ContentSettingsTypes} contentType The name of the
-   *   category to query.
-   * @return {!Promise<!DefaultContentSetting>}
-   */
-  getDefaultValueForContentType(contentType) {}
-
-  /**
-   * Gets a list of sites, grouped by eTLD+1, affected by any content settings
-   * that should be visible to the user.
-   * @return {!Promise<!Array<!SiteGroup>>}
-   */
-  getAllSites() {}
-
-  /**
-   * Returns a list of content settings types that are controlled via a standard
-   * permissions UI and should be made visible to the user.
-   * @param {!string} origin The associated origin for which categories should
-   *     be shown or hidden.
-   * @return {!Promise<!Array<string>>}
-   */
-  getCategoryList(origin) {}
-
-  /**
-   * Get the string which describes the current effective cookie setting.
-   * @return {!Promise<string>}
-   */
-  getCookieSettingDescription() {}
-
-  /**
-   * Gets most recently changed permissions grouped by host and limited to
-   * numSources different origin/profile (inconigto/regular) pairings.
-   * This includes permissions adjusted by embargo, but excludes any set
-   * via policy.
-   * @param {!number} numSources Maximum number of different sources to return
-   * @return {!Promise<!Array<!RecentSitePermissions>>}
-   */
-  getRecentSitePermissions(numSources) {}
-
-  /**
-   * Gets the chooser exceptions for a particular chooser type.
-   * @param {ChooserType} chooserType The chooser type to grab
-   *     exceptions from.
-   * @return {!Promise<!Array<!RawChooserException>>}
-   */
-  getChooserExceptionList(chooserType) {}
-
-  /**
-   * Converts a given number of bytes into a human-readable format, with data
-   * units.
-   * @param {number} numBytes The number of bytes to convert.
-   * @return {!Promise<string>}
-   */
-  getFormattedBytes(numBytes) {}
-
-  /**
-   * Gets the exceptions (site list) for a particular category.
-   * @param {!ContentSettingsTypes} contentType The name of the category to
-   *     query.
-   * @return {!Promise<!Array<!RawSiteException>>}
-   */
-  getExceptionList(contentType) {}
-
-  /**
-   * Gets a list of category permissions for a given origin. Note that this
-   * may be different to the results retrieved by getExceptionList(), since it
-   * combines different sources of data to get a permission's value.
-   * @param {string} origin The origin to look up permissions for.
-   * @param {!Array<!ContentSettingsTypes>} contentTypes A list of
-   *     categories to retrieve the ContentSetting for.
-   * @return {!Promise<!Array<!RawSiteException>>}
-   */
-  getOriginPermissions(origin, contentTypes) {}
-
-  /**
-   * Resets the permissions for a list of categories for a given origin. This
-   * does not support incognito settings or patterns.
-   * @param {string} origin The origin to reset permissions for.
-   * @param {?ContentSettingsTypes} category The category to set the permission
-   *     for. If null, this applies to all categories. (Sometimes it is useful
-   *     to clear any permissions set for all categories.)
-   * @param {!ContentSetting} blanketSetting The setting to set all
-   *     permissions listed in |contentTypes| to.
-   */
-  setOriginPermissions(origin, category, blanketSetting) {}
-
-  /**
-   * Resets the category permission for a given origin (expressed as primary
-   * and secondary patterns). Only use this if intending to remove an
-   * exception - use setOriginPermissions() for origin-scoped settings.
-   * @param {string} primaryPattern The origin to change (primary pattern).
-   * @param {string} secondaryPattern The embedding origin to change
-   *     (secondary pattern).
-   * @param {string} contentType The name of the category to reset.
-   * @param {boolean} incognito Whether this applies only to a current
-   *     incognito session exception.
-   */
-  resetCategoryPermissionForPattern(
-      primaryPattern, secondaryPattern, contentType, incognito) {}
-
-  /**
-   * Removes a particular chooser object permission by origin and embedding
-   * origin.
-   * @param {ChooserType} chooserType The chooser exception type
-   * @param {string} origin The origin to look up the permission for.
-   * @param {string} embeddingOrigin the embedding origin to look up.
-   * @param {!Object} exception The exception to revoke permission for.
-   */
-  resetChooserExceptionForSite(
-      chooserType, origin, embeddingOrigin, exception) {}
-
-  /**
-   * Sets the category permission for a given origin (expressed as primary and
-   * secondary patterns). Only use this if intending to set an exception - use
-   * setOriginPermissions() for origin-scoped settings.
-   * @param {string} primaryPattern The origin to change (primary pattern).
-   * @param {string} secondaryPattern The embedding origin to change
-   *     (secondary pattern).
-   * @param {string} contentType The name of the category to change.
-   * @param {string} value The value to change the permission to.
-   * @param {boolean} incognito Whether this rule applies only to the current
-   *     incognito session.
-   */
-  setCategoryPermissionForPattern(
-      primaryPattern, secondaryPattern, contentType, value, incognito) {}
-
-  /**
-   * Checks whether an origin is valid.
-   * @param {string} origin The origin to check.
-   * @return {!Promise<boolean>} True if the origin is valid.
-   */
-  isOriginValid(origin) {}
-
-  /**
-   * Checks whether a setting is valid.
-   * @param {string} pattern The pattern to check.
-   * @param {ContentSettingsTypes} category What kind of setting,
-   *     e.g. Location, Camera, Cookies, etc.
-   * @return {!Promise<IsValid>} Contains whether or not the pattern is
-   *     valid for the type, and if it is invalid, the reason why.
-   */
-  isPatternValidForType(pattern, category) {}
-
-  /**
-   * Gets the list of default capture devices for a given type of media. List
-   * is returned through a JS call to updateDevicesMenu.
-   * @param {string} type The type to look up.
-   */
-  getDefaultCaptureDevices(type) {}
-
-  /**
-   * Sets a default devices for a given type of media.
-   * @param {string} type The type of media to configure.
-   * @param {string} defaultValue The id of the media device to set.
-   */
-  setDefaultCaptureDevice(type, defaultValue) {}
-
-  /**
-   * observes _all_ of the the protocol handler state, which includes a list
-   * that is returned through JS calls to 'setProtocolHandlers' along with
-   * other state sent with the messages 'setIgnoredProtocolHandler' and
-   * 'setHandlersEnabled'.
-   */
-  observeProtocolHandlers() {}
-
-  /**
-   * Observes one aspect of the protocol handler so that updates to the
-   * enabled/disabled state are sent. A 'setHandlersEnabled' will be sent
-   * from C++ immediately after receiving this observe request and updates
-   * may follow via additional 'setHandlersEnabled' messages.
-   *
-   * If |observeProtocolHandlers| is called, there's no need to call this
-   * observe as well.
-   */
-  observeProtocolHandlersEnabledState() {}
-
-  /**
-   * Enables or disables the ability for sites to ask to become the default
-   * protocol handlers.
-   * @param {boolean} enabled Whether sites can ask to become default.
-   */
-  setProtocolHandlerDefault(enabled) {}
-
-  /**
-   * Sets a certain url as default for a given protocol handler.
-   * @param {string} protocol The protocol to set a default for.
-   * @param {string} url The url to use as the default.
-   */
-  setProtocolDefault(protocol, url) {}
-
-  /**
-   * Deletes a certain protocol handler by url.
-   * @param {string} protocol The protocol to delete the url from.
-   * @param {string} url The url to delete.
-   */
-  removeProtocolHandler(protocol, url) {}
-
-  /**
-   * Fetches the incognito status of the current profile (whether an incognito
-   * profile exists). Returns the results via onIncognitoStatusChanged.
-   */
-  updateIncognitoStatus() {}
-
-  /**
-   * Fetches the currently defined zoom levels for sites. Returns the results
-   * via onZoomLevelsChanged.
-   */
-  fetchZoomLevels() {}
-
-  /**
-   * Removes a zoom levels for a given host.
-   * @param {string} host The host to remove zoom levels for.
-   */
-  removeZoomLevel(host) {}
-
-  /**
-   * Fetches the current block autoplay state. Returns the results via
-   * onBlockAutoplayStatusChanged.
-   */
-  fetchBlockAutoplayStatus() {}
-
-  /**
-   * Clears all the web storage data and cookies for a given etld+1.
-   * @param {string} etldPlus1 The etld+1 to clear data from.
-   */
-  clearEtldPlus1DataAndCookies(etldPlus1) {}
-
-  /**
-   * Clears all the web storage data and cookies for a given origin.
-   * @param {string} origin The origin to clear data from.
-   */
-  clearOriginDataAndCookies(origin) {}
-
-  /**
-   * Record All Sites Page action for metrics.
-   *  @param {number} action number.
-   */
-  recordAction(action) {}
-}
-
-/**
- * @implements {SiteSettingsPrefsBrowserProxy}
- */
-export class SiteSettingsPrefsBrowserProxyImpl {
-  /** @override */
-  setDefaultValueForContentType(contentType, defaultValue) {
-    chrome.send('setDefaultValueForContentType', [contentType, defaultValue]);
-  }
-
-  /** @override */
-  getDefaultValueForContentType(contentType) {
-    return sendWithPromise('getDefaultValueForContentType', contentType);
-  }
-
-  /** @override */
-  getAllSites() {
-    return sendWithPromise('getAllSites');
-  }
-
-  /** @override */
-  getCategoryList(origin) {
-    return sendWithPromise('getCategoryList', origin);
-  }
-
-  /** @override */
-  getCookieSettingDescription() {
-    return sendWithPromise('getCookieSettingDescription');
-  }
-
-  /** @override */
-  getRecentSitePermissions(numSources) {
-    return sendWithPromise('getRecentSitePermissions', numSources);
-  }
-
-  /** @override */
-  getChooserExceptionList(chooserType) {
-    return sendWithPromise('getChooserExceptionList', chooserType);
-  }
-
-  /** @override */
-  getFormattedBytes(numBytes) {
-    return sendWithPromise('getFormattedBytes', numBytes);
-  }
-
-  /** @override */
-  getExceptionList(contentType) {
-    return sendWithPromise('getExceptionList', contentType);
-  }
-
-  /** @override */
-  getOriginPermissions(origin, contentTypes) {
-    return sendWithPromise('getOriginPermissions', origin, contentTypes);
-  }
-
-  /** @override */
-  setOriginPermissions(origin, contentTypes, blanketSetting) {
-    chrome.send('setOriginPermissions', [origin, contentTypes, blanketSetting]);
-  }
-
-  /** @override */
-  resetCategoryPermissionForPattern(
-      primaryPattern, secondaryPattern, contentType, incognito) {
-    chrome.send(
-        'resetCategoryPermissionForPattern',
-        [primaryPattern, secondaryPattern, contentType, incognito]);
-  }
-
-  /** @override */
-  resetChooserExceptionForSite(
-      chooserType, origin, embeddingOrigin, exception) {
-    chrome.send(
-        'resetChooserExceptionForSite',
-        [chooserType, origin, embeddingOrigin, exception]);
-  }
-
-  /** @override */
-  setCategoryPermissionForPattern(
-      primaryPattern, secondaryPattern, contentType, value, incognito) {
-    chrome.send(
-        'setCategoryPermissionForPattern',
-        [primaryPattern, secondaryPattern, contentType, value, incognito]);
-  }
-
-  /** @override */
-  isOriginValid(origin) {
-    return sendWithPromise('isOriginValid', origin);
-  }
-
-  /** @override */
-  isPatternValidForType(pattern, category) {
-    return sendWithPromise('isPatternValidForType', pattern, category);
-  }
-
-  /** @override */
-  getDefaultCaptureDevices(type) {
-    chrome.send('getDefaultCaptureDevices', [type]);
-  }
-
-  /** @override */
-  setDefaultCaptureDevice(type, defaultValue) {
-    chrome.send('setDefaultCaptureDevice', [type, defaultValue]);
-  }
-
-  /** @override */
-  observeProtocolHandlers() {
-    chrome.send('observeProtocolHandlers');
-  }
-
-  /** @override */
-  observeProtocolHandlersEnabledState() {
-    chrome.send('observeProtocolHandlersEnabledState');
-  }
-
-  /** @override */
-  setProtocolHandlerDefault(enabled) {
-    chrome.send('setHandlersEnabled', [enabled]);
-  }
-
-  /** @override */
-  setProtocolDefault(protocol, url) {
-    chrome.send('setDefault', [protocol, url]);
-  }
-
-  /** @override */
-  removeProtocolHandler(protocol, url) {
-    chrome.send('removeHandler', [protocol, url]);
-  }
-
-  /** @override */
-  updateIncognitoStatus() {
-    chrome.send('updateIncognitoStatus');
-  }
-
-  /** @override */
-  fetchZoomLevels() {
-    chrome.send('fetchZoomLevels');
-  }
-
-  /** @override */
-  removeZoomLevel(host) {
-    chrome.send('removeZoomLevel', [host]);
-  }
-
-  /** @override */
-  fetchBlockAutoplayStatus() {
-    chrome.send('fetchBlockAutoplayStatus');
-  }
-
-  /** @override */
-  clearEtldPlus1DataAndCookies(etldPlus1) {
-    chrome.send('clearEtldPlus1DataAndCookies', [etldPlus1]);
-  }
-
-  /** @override */
-  clearOriginDataAndCookies(origin) {
-    chrome.send('clearUsage', [origin]);
-  }
-
-  /** @override */
-  recordAction(action) {
-    chrome.send('recordAction', [action]);
-  }
-
-  /** @return {!SiteSettingsPrefsBrowserProxy} */
-  static getInstance() {
-    return instance || (instance = new SiteSettingsPrefsBrowserProxyImpl());
-  }
-
-  /** @param {!SiteSettingsPrefsBrowserProxy} obj */
-  static setInstance(obj) {
-    instance = obj;
-  }
-}
-
-/** @type {?SiteSettingsPrefsBrowserProxy} */
-let instance = null;
diff --git a/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts
new file mode 100644
index 0000000..01572546b
--- /dev/null
+++ b/chrome/browser/resources/settings/site_settings/site_settings_prefs_browser_proxy.ts
@@ -0,0 +1,550 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview A helper object used from the "Site Settings" section to
+ * interact with the content settings prefs.
+ */
+
+// clang-format off
+import {sendWithPromise} from 'chrome://resources/js/cr.m.js';
+
+import {ChooserType,ContentSetting,ContentSettingsTypes,SiteSettingSource} from './constants.js';
+// clang-format on
+
+/**
+ * The handler will send a policy source that is similar, but not exactly the
+ * same as a ControlledBy value. If the ContentSettingProvider is omitted it
+ * should be treated as 'default'.
+ */
+export enum ContentSettingProvider {
+  POLICY = 'policy',
+  SUPERVISED_USER = 'supervised_user',
+  EXTENSION = 'extension',
+  INSTALLED_WEBAPP_PROVIDER = 'installed_webapp_provider',
+  NOTIFICATION_ANDROID = 'notification_android',
+  EPHEMERAL = 'ephemeral',
+  PREFERENCE = 'preference',
+  DEFAULT = 'default',
+  TESTS = 'tests',
+  TESTS_OTHER = 'tests_other'
+}
+
+/**
+ * Stores information about if a content setting is valid, and why.
+ */
+type IsValid = {
+  isValid: boolean,
+  reason: string|null,
+};
+
+/**
+ * Stores origin information. The |hasPermissionSettings| will be set to true
+ * when this origin has permissions or when there is a pattern permission
+ * affecting this origin.
+ */
+export type OriginInfo = {
+  origin: string,
+  engagement: number,
+  usage: number,
+  numCookies: number,
+  hasPermissionSettings: boolean,
+  isInstalled: boolean,
+};
+
+/**
+ * Represents a list of sites, grouped under the same eTLD+1. For example, an
+ * origin "https://www.example.com" would be grouped together with
+ * "https://login.example.com" and "http://example.com" under a common eTLD+1 of
+ * "example.com".
+ */
+export type SiteGroup = {
+  etldPlus1: string,
+  numCookies: number,
+  origins: Array<OriginInfo>,
+  hasInstalledPWA: boolean,
+};
+
+/**
+ * The site exception information passed from the C++ handler.
+ * See also: SiteException.
+ */
+export type RawSiteException = {
+  embeddingOrigin: string,
+  incognito: boolean,
+  isEmbargoed: boolean,
+  origin: string,
+  displayName: string,
+  settingDetail: string|null,
+  type: string,
+  setting: ContentSetting,
+  source: SiteSettingSource,
+};
+
+/**
+ * The site exception after it has been converted/filtered for UI use.
+ * See also: RawSiteException.
+ */
+export type SiteException = {
+  category: ContentSettingsTypes,
+  embeddingOrigin: string,
+  incognito: boolean,
+  isEmbargoed: boolean,
+  origin: string,
+  displayName: string,
+  settingDetail: string|null,
+  setting: ContentSetting,
+  enforcement: chrome.settingsPrivate.Enforcement|null,
+  controlledBy: chrome.settingsPrivate.ControlledBy,
+  // <if expr="chromeos">
+  showAndroidSmsNote?: boolean,
+  // </if>
+};
+
+/**
+ * Represents a list of exceptions recently configured for a site, where recent
+ * is defined by the maximum number of sources parameter passed to
+ * GetRecentSitePermissions.
+ */
+export type RecentSitePermissions = {
+  origin: string,
+  incognito: boolean,
+  recentPermissions: Array<RawSiteException>,
+};
+
+/**
+ * The chooser exception information passed from the C++ handler.
+ * See also: ChooserException.
+ */
+export type RawChooserException = {
+  chooserType: ChooserType,
+  displayName: string,
+  object: Object,
+  sites: Array<RawSiteException>,
+};
+
+/**
+ * The chooser exception after it has been converted/filtered for UI use.
+ * See also: RawChooserException.
+ */
+export type ChooserException = {
+  chooserType: ChooserType,
+  displayName: string,
+  object: Object,
+  sites: Array<SiteException>,
+};
+
+export type DefaultContentSetting = {
+  setting: ContentSetting,
+  source: ContentSettingProvider,
+};
+
+export type MediaPickerEntry = {
+  name: string,
+  id: string,
+};
+
+type ProtocolHandlerEntry = {
+  protocol: string,
+  spec: string,
+};
+
+export type ZoomLevelEntry = {
+  origin: string,
+  setting: string,
+  source: string,
+  zoom: string,
+};
+
+export interface SiteSettingsPrefsBrowserProxy {
+  /**
+   * Sets the default value for a site settings category.
+   * @param contentType The name of the category to change.
+   * @param defaultValue The name of the value to set as default.
+   */
+  setDefaultValueForContentType(contentType: string, defaultValue: string):
+      void;
+
+  /**
+   * Gets the default value for a site settings category.
+   */
+  getDefaultValueForContentType(contentType: ContentSettingsTypes):
+      Promise<DefaultContentSetting>;
+
+  /**
+   * Gets a list of sites, grouped by eTLD+1, affected by any content settings
+   * that should be visible to the user.
+   */
+  getAllSites(): Promise<Array<SiteGroup>>;
+
+  /**
+   * Returns a list of content settings types that are controlled via a standard
+   * permissions UI and should be made visible to the user.
+   * @param origin The associated origin for which categories should be shown or
+   *     hidden.
+   */
+  getCategoryList(origin: string): Promise<Array<ContentSettingsTypes>>;
+
+  /**
+   * Get the string which describes the current effective cookie setting.
+   */
+  getCookieSettingDescription(): Promise<string>;
+
+  /**
+   * Gets most recently changed permissions grouped by host and limited to
+   * numSources different origin/profile (inconigto/regular) pairings.
+   * This includes permissions adjusted by embargo, but excludes any set
+   * via policy.
+   * @param numSources Maximum number of different sources to return
+   */
+  getRecentSitePermissions(numSources: number):
+      Promise<Array<RecentSitePermissions>>;
+
+  /**
+   * Gets the chooser exceptions for a particular chooser type.
+   * @param chooserType The chooser type to grab exceptions from.
+   */
+  getChooserExceptionList(chooserType: ChooserType):
+      Promise<Array<RawChooserException>>;
+
+  /**
+   * Converts a given number of bytes into a human-readable format, with data
+   * units.
+   */
+  getFormattedBytes(numBytes: number): Promise<string>;
+
+  /**
+   * Gets the exceptions (site list) for a particular category.
+   * @param contentType The name of the category to query.
+   */
+  getExceptionList(contentType: ContentSettingsTypes):
+      Promise<Array<RawSiteException>>;
+
+  /**
+   * Gets a list of category permissions for a given origin. Note that this
+   * may be different to the results retrieved by getExceptionList(), since it
+   * combines different sources of data to get a permission's value.
+   * @param origin The origin to look up permissions for.
+   * @param contentTypes A list of categories to retrieve the ContentSetting
+   *     for.
+   */
+  getOriginPermissions(
+      origin: string, contentTypes: Array<ContentSettingsTypes>):
+      Promise<Array<RawSiteException>>;
+
+  /**
+   * Resets the permissions for a list of categories for a given origin. This
+   * does not support incognito settings or patterns.
+   * @param origin The origin to reset permissions for.
+   * @param category to set the permission for. If null, this applies to all
+   *     categories. (Sometimes it is useful to clear any permissions set for
+   *     all categories.)
+   * @param blanketSetting The setting to set all permissions listed in
+   *     |contentTypes| to.
+   */
+  setOriginPermissions(
+      origin: string, category: ContentSettingsTypes|null,
+      blanketSetting: ContentSetting): void;
+
+  /**
+   * Resets the category permission for a given origin (expressed as primary
+   * and secondary patterns). Only use this if intending to remove an
+   * exception - use setOriginPermissions() for origin-scoped settings.
+   * @param primaryPattern The origin to change (primary pattern).
+   * @param secondaryPattern The embedding origin to change (secondary
+   *     pattern).
+   * @param contentType The name of the category to reset.
+   * @param incognito Whether this applies only to a current
+   *     incognito session exception.
+   */
+  resetCategoryPermissionForPattern(
+      primaryPattern: string, secondaryPattern: string, contentType: string,
+      incognito: boolean): void;
+
+  /**
+   * Removes a particular chooser object permission by origin and embedding
+   * origin.
+   * @param chooserType The chooser exception type
+   * @param origin The origin to look up the permission for.
+   * @param embeddingOrigin the embedding origin to look up.
+   * @param exception The exception to revoke permission for.
+   */
+  resetChooserExceptionForSite(
+      chooserType: ChooserType, origin: string, embeddingOrigin: string,
+      exception: Object): void;
+
+  /**
+   * Sets the category permission for a given origin (expressed as primary and
+   * secondary patterns). Only use this if intending to set an exception - use
+   * setOriginPermissions() for origin-scoped settings.
+   * @param primaryPattern The origin to change (primary pattern).
+   * @param secondaryPattern The embedding origin to change (secondary pattern).
+   * @param contentType The name of the category to change.
+   * @param value The value to change the permission to.
+   * @param incognito Whether this rule applies only to the current incognito
+   *     session.
+   */
+  setCategoryPermissionForPattern(
+      primaryPattern: string, secondaryPattern: string, contentType: string,
+      value: string, incognito: boolean): void;
+
+  /**
+   * Checks whether an origin is valid.
+   */
+  isOriginValid(origin: string): Promise<boolean>;
+
+  /**
+   * Checks whether a setting is valid.
+   * @param pattern The pattern to check.
+   * @param category What kind of setting, e.g. Location, Camera, Cookies, etc.
+   * @return Contains whether or not the pattern is valid for the type, and if
+   *     it is invalid, the reason why.
+   */
+  isPatternValidForType(pattern: string, category: ContentSettingsTypes):
+      Promise<IsValid>;
+
+  /**
+   * Gets the list of default capture devices for a given type of media. List
+   * is returned through a JS call to updateDevicesMenu.
+   * @param type The type to look up.
+   */
+  getDefaultCaptureDevices(type: string): void;
+
+  /**
+   * Sets a default devices for a given type of media.
+   * @param type The type of media to configure.
+   * @param defaultValue The id of the media device to set.
+   */
+  setDefaultCaptureDevice(type: string, defaultValue: string): void;
+
+  /**
+   * observes _all_ of the the protocol handler state, which includes a list
+   * that is returned through JS calls to 'setProtocolHandlers' along with
+   * other state sent with the messages 'setIgnoredProtocolHandler' and
+   * 'setHandlersEnabled'.
+   */
+  observeProtocolHandlers(): void;
+
+  /**
+   * Observes one aspect of the protocol handler so that updates to the
+   * enabled/disabled state are sent. A 'setHandlersEnabled' will be sent
+   * from C++ immediately after receiving this observe request and updates
+   * may follow via additional 'setHandlersEnabled' messages.
+   *
+   * If |observeProtocolHandlers| is called, there's no need to call this
+   * observe as well.
+   */
+  observeProtocolHandlersEnabledState(): void;
+
+  /**
+   * Enables or disables the ability for sites to ask to become the default
+   * protocol handlers.
+   * @param enabled Whether sites can ask to become default.
+   */
+  setProtocolHandlerDefault(enabled: boolean): void;
+
+  /**
+   * Sets a certain url as default for a given protocol handler.
+   * @param protocol The protocol to set a default for.
+   * @param url The url to use as the default.
+   */
+  setProtocolDefault(protocol: string, url: string): void;
+
+  /**
+   * Deletes a certain protocol handler by url.
+   * @param protocol The protocol to delete the url from.
+   * @param url The url to delete.
+   */
+  removeProtocolHandler(protocol: string, url: string): void;
+
+  /**
+   * Fetches the incognito status of the current profile (whether an incognito
+   * profile exists). Returns the results via onIncognitoStatusChanged.
+   */
+  updateIncognitoStatus(): void;
+
+  /**
+   * Fetches the currently defined zoom levels for sites. Returns the results
+   * via onZoomLevelsChanged.
+   */
+  fetchZoomLevels(): void;
+
+  /**
+   * Removes a zoom levels for a given host.
+   * @param host The host to remove zoom levels for.
+   */
+  removeZoomLevel(host: string): void;
+
+  /**
+   * Fetches the current block autoplay state. Returns the results via
+   * onBlockAutoplayStatusChanged.
+   */
+  fetchBlockAutoplayStatus(): void;
+
+  /**
+   * Clears all the web storage data and cookies for a given etld+1.
+   * @param etldPlus1 The etld+1 to clear data from.
+   */
+  clearEtldPlus1DataAndCookies(etldPlus1: string): void;
+
+  /**
+   * Clears all the web storage data and cookies for a given origin.
+   * @param origin The origin to clear data from.
+   */
+  clearOriginDataAndCookies(origin: string): void;
+
+  /**
+   * Record All Sites Page action for metrics.
+   * @param action number.
+   */
+  recordAction(action: number): void;
+}
+
+export class SiteSettingsPrefsBrowserProxyImpl implements
+    SiteSettingsPrefsBrowserProxy {
+  setDefaultValueForContentType(contentType: string, defaultValue: string) {
+    chrome.send('setDefaultValueForContentType', [contentType, defaultValue]);
+  }
+
+  getDefaultValueForContentType(contentType: ContentSettingsTypes) {
+    return sendWithPromise('getDefaultValueForContentType', contentType);
+  }
+
+  getAllSites() {
+    return sendWithPromise('getAllSites');
+  }
+
+  getCategoryList(origin: string) {
+    return sendWithPromise('getCategoryList', origin);
+  }
+
+  getCookieSettingDescription() {
+    return sendWithPromise('getCookieSettingDescription');
+  }
+
+  getRecentSitePermissions(numSources: number) {
+    return sendWithPromise('getRecentSitePermissions', numSources);
+  }
+
+  getChooserExceptionList(chooserType: ChooserType) {
+    return sendWithPromise('getChooserExceptionList', chooserType);
+  }
+
+  getFormattedBytes(numBytes: number) {
+    return sendWithPromise('getFormattedBytes', numBytes);
+  }
+
+  getExceptionList(contentType: ContentSettingsTypes) {
+    return sendWithPromise('getExceptionList', contentType);
+  }
+
+  getOriginPermissions(
+      origin: string, contentTypes: Array<ContentSettingsTypes>) {
+    return sendWithPromise('getOriginPermissions', origin, contentTypes);
+  }
+
+  setOriginPermissions(
+      origin: string, category: ContentSettingsTypes|null,
+      blanketSetting: ContentSetting) {
+    chrome.send('setOriginPermissions', [origin, category, blanketSetting]);
+  }
+
+  resetCategoryPermissionForPattern(
+      primaryPattern: string, secondaryPattern: string, contentType: string,
+      incognito: boolean) {
+    chrome.send(
+        'resetCategoryPermissionForPattern',
+        [primaryPattern, secondaryPattern, contentType, incognito]);
+  }
+
+  resetChooserExceptionForSite(
+      chooserType: ChooserType, origin: string, embeddingOrigin: string,
+      exception: Object) {
+    chrome.send(
+        'resetChooserExceptionForSite',
+        [chooserType, origin, embeddingOrigin, exception]);
+  }
+
+  setCategoryPermissionForPattern(
+      primaryPattern: string, secondaryPattern: string, contentType: string,
+      value: string, incognito: boolean) {
+    chrome.send(
+        'setCategoryPermissionForPattern',
+        [primaryPattern, secondaryPattern, contentType, value, incognito]);
+  }
+
+  isOriginValid(origin: string) {
+    return sendWithPromise('isOriginValid', origin);
+  }
+
+  isPatternValidForType(pattern: string, category: ContentSettingsTypes) {
+    return sendWithPromise('isPatternValidForType', pattern, category);
+  }
+
+  getDefaultCaptureDevices(type: string) {
+    chrome.send('getDefaultCaptureDevices', [type]);
+  }
+
+  setDefaultCaptureDevice(type: string, defaultValue: string) {
+    chrome.send('setDefaultCaptureDevice', [type, defaultValue]);
+  }
+
+  observeProtocolHandlers() {
+    chrome.send('observeProtocolHandlers');
+  }
+
+  observeProtocolHandlersEnabledState() {
+    chrome.send('observeProtocolHandlersEnabledState');
+  }
+
+  setProtocolHandlerDefault(enabled: boolean) {
+    chrome.send('setHandlersEnabled', [enabled]);
+  }
+
+  setProtocolDefault(protocol: string, url: string) {
+    chrome.send('setDefault', [protocol, url]);
+  }
+
+  removeProtocolHandler(protocol: string, url: string) {
+    chrome.send('removeHandler', [protocol, url]);
+  }
+
+  updateIncognitoStatus() {
+    chrome.send('updateIncognitoStatus');
+  }
+
+  fetchZoomLevels() {
+    chrome.send('fetchZoomLevels');
+  }
+
+  removeZoomLevel(host: string) {
+    chrome.send('removeZoomLevel', [host]);
+  }
+
+  fetchBlockAutoplayStatus() {
+    chrome.send('fetchBlockAutoplayStatus');
+  }
+
+  clearEtldPlus1DataAndCookies(etldPlus1: string) {
+    chrome.send('clearEtldPlus1DataAndCookies', [etldPlus1]);
+  }
+
+  clearOriginDataAndCookies(origin: string) {
+    chrome.send('clearUsage', [origin]);
+  }
+
+  recordAction(action: number) {
+    chrome.send('recordAction', [action]);
+  }
+
+  static getInstance(): SiteSettingsPrefsBrowserProxy {
+    return instance || (instance = new SiteSettingsPrefsBrowserProxyImpl());
+  }
+
+  static setInstance(obj: SiteSettingsPrefsBrowserProxy) {
+    instance = obj;
+  }
+}
+
+let instance: SiteSettingsPrefsBrowserProxy|null = null;
diff --git a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
index b16c878e..285b7cd 100644
--- a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
+++ b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
@@ -41,7 +41,7 @@
 const SettingsRecentSitePermissionsElementBase =
     mixinBehaviors(
         [WebUIListenerBehavior, I18nBehavior],
-        SiteSettingsMixin(RouteObserverMixin(PolymerElement))) as {
+        RouteObserverMixin(SiteSettingsMixin(PolymerElement))) as {
       new (): PolymerElement & I18nBehavior & WebUIListenerBehavior &
       SiteSettingsMixinInterface & RouteObserverMixinInterface
     };
@@ -214,16 +214,14 @@
    */
   private getDisplayName_(recentSitePermissions: RecentSitePermissions):
       string {
-    const url = this.toUrl(recentSitePermissions.origin);
-    return url.host;
+    return this.toUrl(recentSitePermissions.origin)!.host;
   }
 
   /**
    * @return the site scheme for the origin of a set of recent permissions.
    */
   private getSiteScheme_({origin}: RecentSitePermissions): string {
-    const url = this.toUrl(origin);
-    const scheme = url.protocol.slice(0, -1);
+    const scheme = this.toUrl(origin)!.protocol.slice(0, -1);
     return scheme === 'https' ? '' : scheme;
   }
 
@@ -274,7 +272,8 @@
   private getPermissionGroupText_(
       setting: string, exceptions: Array<RawSiteException>): string {
     const typeStrings = exceptions.map(
-        exception => this.getI18nContentTypeString_(exception.type));
+        exception => this.getI18nContentTypeString_(
+            exception.type as ContentSettingsTypes));
 
     if (exceptions.length === 0) {
       return '';
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
index 42a42ee..c57768c 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
@@ -164,7 +164,7 @@
     // PROTECTED_CONTENT
     if (category === ContentSettingsTypes.ZOOM_LEVELS ||
         category === ContentSettingsTypes.PROTECTED_CONTENT ||
-        category === 'pdfDocuments') {
+        category === ContentSettingsTypes.PDF_DOCUMENTS) {
       return Promise.resolve();
     }
 
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
index b771f3b..097e859 100644
--- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
+++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
@@ -226,7 +226,7 @@
     },
     {
       route: routes.SITE_SETTINGS_PDF_DOCUMENTS,
-      id: 'pdfDocuments',
+      id: Id.PDF_DOCUMENTS,
       label: 'siteSettingsPdfDocuments',
       icon: 'settings:pdf',
       enabledLabel: 'siteSettingsPdfsAllowed',
@@ -390,7 +390,7 @@
               Id.SOUND,
               Id.ADS,
               Id.ZOOM_LEVELS,
-              'pdfDocuments',
+              Id.PDF_DOCUMENTS,
               Id.PROTECTED_CONTENT,
               Id.MIXEDSCRIPT,
             ]),
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc
index 9739f56..b413dc2 100644
--- a/chrome/browser/sync/chrome_sync_client.cc
+++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -442,10 +442,7 @@
   // See crbug/1013732 for details.
   if (app_list::AppListSyncableServiceFactory::GetForProfile(profile_) &&
       !chromeos::switches::IsTabletFormFactor()) {
-    // TODO(https://crbug.com/1227417): Remove SplitSettingsSync after migrating
-    // the affected tests.
-    if (chromeos::features::IsSplitSettingsSyncEnabled() ||
-        chromeos::features::IsSyncSettingsCategorizationEnabled()) {
+    if (chromeos::features::IsSyncSettingsCategorizationEnabled()) {
       // Runs in sync transport-mode and full-sync mode.
       controllers.push_back(
           std::make_unique<OsSyncableServiceModelTypeController>(
@@ -483,8 +480,7 @@
         GetSyncableServiceForType(syncer::ARC_PACKAGE), dump_stack,
         sync_service, profile_));
   }
-  if (chromeos::features::IsSplitSettingsSyncEnabled() ||
-      chromeos::features::IsSyncSettingsCategorizationEnabled()) {
+  if (chromeos::features::IsSyncSettingsCategorizationEnabled()) {
     if (!disabled_types.Has(syncer::OS_PREFERENCES)) {
       controllers.push_back(
           std::make_unique<OsSyncableServiceModelTypeController>(
@@ -538,7 +534,7 @@
           profile_->GetPrefs(), sync_service));
     }
   } else {
-    // SplitSettingsSync and SyncSettingsCategorization are disabled.
+    // SyncSettingsCategorization is disabled.
     if (!disabled_types.Has(syncer::WIFI_CONFIGURATIONS) &&
         base::FeatureList::IsEnabled(switches::kSyncWifiConfigurations) &&
         WifiConfigurationSyncServiceFactory::ShouldRunInProfile(profile_)) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
index 83240c4..02a6fb2 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarMediator.java
@@ -407,7 +407,8 @@
     }
 
     private void updateNewTabButtonVisibility() {
-        boolean isShownTabSwitcherState = mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER;
+        boolean isShownTabSwitcherState = mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER
+                || mStartSurfaceState == StartSurfaceState.SHOWING_TABSWITCHER;
 
         // This button is only shown for homepage when accessibility is enabled and
         // OverviewListLayout is shown as the tab switcher instead of the start surface.
@@ -418,7 +419,8 @@
     }
 
     private void updateHomeButtonVisibility() {
-        boolean isShownTabSwitcherState = mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER;
+        boolean isShownTabSwitcherState = mStartSurfaceState == StartSurfaceState.SHOWN_TABSWITCHER
+                || mStartSurfaceState == StartSurfaceState.SHOWING_TABSWITCHER;
         boolean shouldShow = mHomepageEnabled && isShownTabSwitcherState
                 && !mPropertyModel.get(IS_INCOGNITO) && mShowHomeButtonOnTabSwitcher
                 && mShouldShowStartSurfaceAsHomepage;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
index 9c954f8..10d60ef8 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/StartSurfaceToolbarView.java
@@ -402,8 +402,8 @@
     }
 
     /**
-     * If transition animations shouldn't show, start animation to show or hide toolbar; Otherwise
-     * show transition animations.
+     * If transition animations shouldn't show, update the visibility of toolbar; Otherwise if
+     * toolbar is already showing and transition animations should show, show transition animations.
      */
     private void startToolbarVisibilityAnimations() {
         boolean shouldShowStartSurfaceToolbar = mInStartSurfaceMode && mShouldShow;
@@ -414,10 +414,10 @@
             if (shouldShowStartSurfaceToolbar == mIsShowing) return;
             mIsShowing = shouldShowStartSurfaceToolbar;
 
-            // If transition animations of sub components shouldn't show, the fade animator of
-            // toolbar view should show by default.
-            addFadeAnimator(this, shouldShowStartSurfaceToolbar, MEDIUM_DURATION_MS,
-                    /* delay = */ 0, Interpolators.LINEAR_INTERPOLATOR);
+            // TODO(1139024): If transition animations of sub components shouldn't show, the fade
+            // animator of toolbar view should always show by default. Not showing fade animator is
+            // a temporary solution for crbug.com/1249377.
+            setVisibility(getVisibility(shouldShowStartSurfaceToolbar));
         } else if (shouldShowStartSurfaceToolbar) {
             addTransitionAnimators();
         }
diff --git a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc
index 7cf4e0ef..9d777c07 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_context_menu.cc
@@ -11,11 +11,11 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/crosapi/browser_manager.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_terminal.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_manager.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_manager_factory.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
diff --git a/chrome/browser/ui/ash/desk_template_app_launch_handler.cc b/chrome/browser/ui/ash/desk_template_app_launch_handler.cc
index 830f5e7..e88e503e 100644
--- a/chrome/browser/ui/ash/desk_template_app_launch_handler.cc
+++ b/chrome/browser/ui/ash/desk_template_app_launch_handler.cc
@@ -11,8 +11,8 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/ash/desk_template_app_launch_handler.h b/chrome/browser/ui/ash/desk_template_app_launch_handler.h
index 3805879..65809e1 100644
--- a/chrome/browser/ui/ash/desk_template_app_launch_handler.h
+++ b/chrome/browser/ui/ash/desk_template_app_launch_handler.h
@@ -8,7 +8,7 @@
 #include <memory>
 
 #include "base/memory/weak_ptr.h"
-#include "chrome/browser/ash/full_restore/app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/app_launch_handler.h"
 #include "components/app_restore/desk_template_read_handler.h"
 
 class Profile;
diff --git a/chrome/browser/ui/ash/multi_user/multi_profile_support.cc b/chrome/browser/ui/ash/multi_user/multi_profile_support.cc
index 0179adcb..df70a57 100644
--- a/chrome/browser/ui/ash/multi_user/multi_profile_support.cc
+++ b/chrome/browser/ui/ash/multi_user/multi_profile_support.cc
@@ -11,7 +11,7 @@
 #include "ash/public/cpp/multi_user_window_manager_observer.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
index db52a8993..5936714 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_app_window_arc_tracker.cc
@@ -18,11 +18,11 @@
 #include "chrome/browser/apps/app_service/app_icon_factory.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/ash/app_restore/arc_window_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/arc_optin_uma.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
-#include "chrome/browser/ash/full_restore/arc_window_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
diff --git a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
index d8adb42..52bfea8e 100644
--- a/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/shelf/app_service/app_service_shelf_context_menu.cc
@@ -12,13 +12,13 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/menu_util.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/arc/app_shortcuts/arc_app_shortcuts_menu_builder.h"
 #include "chrome/browser/ash/crosapi/browser_manager.h"
 #include "chrome/browser/ash/crostini/crostini_manager.h"
 #include "chrome/browser/ash/crostini/crostini_shelf_utils.h"
 #include "chrome/browser/ash/crostini/crostini_terminal.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service.h"
 #include "chrome/browser/ash/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_manager.h"
diff --git a/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc b/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
index 4121f7b..b4bcce5 100644
--- a/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.cc
@@ -4,9 +4,9 @@
 
 #include "chrome/browser/ui/ash/shelf/arc_shelf_spinner_item_controller.h"
 
+#include "chrome/browser/ash/app_restore/arc_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
-#include "chrome/browser/ash/full_restore/arc_app_launch_handler.h"
-#include "chrome/browser/ash/full_restore/full_restore_arc_task_handler.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/ash/shelf/shelf_spinner_controller.h"
diff --git a/chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.cc b/chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.cc
index b9cc63a..39af5f8e 100644
--- a/chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.cc
+++ b/chrome/browser/ui/ash/shelf/browser_shortcut_shelf_item_controller.cc
@@ -13,7 +13,7 @@
 #include "ash/wm/desks/desks_util.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/ash_util.h"
 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
diff --git a/chrome/browser/ui/ash/shelf/shelf_context_menu.cc b/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
index c181521..ecd8729 100644
--- a/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/shelf/shelf_context_menu.cc
@@ -15,9 +15,9 @@
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/ash/accessibility/accessibility_manager.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/crostini/crostini_shelf_utils.h"
 #include "chrome/browser/ash/crostini/crostini_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/internal_app/internal_app_metadata.h"
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
index bc987e3..93310ab5 100644
--- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -41,6 +42,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/ui_base_features.h"
 #include "ui/gfx/image/image_skia.h"
 
 using bookmarks::BookmarkModel;
@@ -82,7 +84,13 @@
 
 class BookmarkBrowsertest : public InProcessBrowserTest {
  public:
-  BookmarkBrowsertest() {}
+  BookmarkBrowsertest() {
+    // This needs to be disabled so that animations are guaranteed to work.
+#if defined(OS_WIN)
+    feature_list_.InitWithFeatures(
+        {}, {features::kApplyNativeOcclusionToCompositor});
+#endif
+  }
 
   bool IsVisible() {
     return browser()->bookmark_bar_state() == BookmarkBar::SHOW;
@@ -115,6 +123,10 @@
   base::HistogramTester* histogram_tester() { return &histogram_tester_; }
 
  private:
+#if defined(OS_WIN)
+  base::test::ScopedFeatureList feature_list_;
+#endif
+
   // We make the histogram tester a member field to make sure it starts
   // recording as early as possible.
   base::HistogramTester histogram_tester_;
diff --git a/chrome/browser/ui/startup/startup_browser_creator.cc b/chrome/browser/ui/startup/startup_browser_creator.cc
index 7ec50d48..118d3fab 100644
--- a/chrome/browser/ui/startup/startup_browser_creator.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator.cc
@@ -90,7 +90,7 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_switches.h"
 #include "chrome/browser/ash/app_mode/app_launch_utils.h"
-#include "chrome/browser/ash/full_restore/full_restore_service.h"
+#include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/lifetime/application_lifetime.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "components/user_manager/user_manager.h"
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
index 85ff68b..e0858f2 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu_unittest.cc
@@ -34,6 +34,7 @@
 #include "ui/base/clipboard/test/test_clipboard.h"
 #include "ui/events/platform/platform_event_source.h"
 #include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/test/scoped_views_test_helper.h"
 
 #if defined(OS_WIN)
 #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h"
@@ -96,6 +97,7 @@
   }
 
   content::BrowserTaskEnvironment task_environment_;
+  views::ScopedViewsTestHelper views_test_helper_;
   std::unique_ptr<TestingProfile> profile_;
   BookmarkModel* model_;
   TestingPageNavigator navigator_;
diff --git a/chrome/browser/ui/views/download/download_item_view.cc b/chrome/browser/ui/views/download/download_item_view.cc
index 9d432aa..568b998 100644
--- a/chrome/browser/ui/views/download/download_item_view.cc
+++ b/chrome/browser/ui/views/download/download_item_view.cc
@@ -1117,6 +1117,7 @@
     case download::DOWNLOAD_DANGER_TYPE_BLOCKED_PASSWORD_PROTECTED:
     case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_BLOCK:
     case download::DOWNLOAD_DANGER_TYPE_DANGEROUS_ACCOUNT_COMPROMISE:
+    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
       return kError;
     case download::DOWNLOAD_DANGER_TYPE_SENSITIVE_CONTENT_WARNING:
       return kWarning;
@@ -1129,7 +1130,6 @@
           ui::NativeTheme::kColorId_DefaultIconColor, non_error_icon_size);
     case download::DOWNLOAD_DANGER_TYPE_BLOCKED_UNSUPPORTED_FILETYPE:
     case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_SAFE:
-    case download::DOWNLOAD_DANGER_TYPE_DEEP_SCANNED_OPENED_DANGEROUS:
     case download::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS:
     case download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT:
     case download::DOWNLOAD_DANGER_TYPE_USER_VALIDATED:
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
index 6e850aa..c763979 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -157,9 +157,14 @@
 SkColor BrowserNonClientFrameView::GetFrameColor(
     BrowserFrameActiveState active_state) const {
   return GetFrameThemeProvider()->GetColor(
-      ShouldPaintAsActive(active_state)
-          ? ThemeProperties::COLOR_FRAME_ACTIVE
-          : ThemeProperties::COLOR_FRAME_INACTIVE);
+      GetTabStripBackgroundColorId(active_state));
+}
+
+int BrowserNonClientFrameView::GetTabStripBackgroundColorId(
+    BrowserFrameActiveState active_state) const {
+  return ShouldPaintAsActive(active_state)
+             ? ThemeProperties::COLOR_FRAME_ACTIVE
+             : ThemeProperties::COLOR_FRAME_INACTIVE;
 }
 
 void BrowserNonClientFrameView::UpdateFrameColor() {
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
index 6e3732c..15f98bd 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -105,6 +105,12 @@
   SkColor GetFrameColor(BrowserFrameActiveState active_state =
                             BrowserFrameActiveState::kUseCurrent) const;
 
+  // Returns the background color id for the tab strip, for use with a
+  // `ThemeProvider`.
+  int GetTabStripBackgroundColorId(
+      BrowserFrameActiveState active =
+          BrowserFrameActiveState::kUseCurrent) const;
+
   // Called by BrowserView to signal the frame color has changed and needs
   // to be repainted.
   virtual void UpdateFrameColor();
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index d677978e..6607503 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -653,7 +653,7 @@
   devtools_web_view->SetVisible(false);
 
   auto contents_web_view =
-      std::make_unique<ContentsWebView>(browser_->profile());
+      std::make_unique<ContentsWebView>(browser_->profile(), this);
   contents_web_view->SetID(VIEW_ID_TAB_CONTAINER);
 
   auto contents_container = std::make_unique<views::View>();
@@ -1818,6 +1818,12 @@
   }
 }
 
+void BrowserView::PaintAsActiveChanged() {
+  if (contents_web_view_) {
+    contents_web_view_->PaintAsActiveChanged();
+  }
+}
+
 void BrowserView::DestroyBrowser() {
   // After this returns other parts of Chrome are going to be shutdown. Close
   // the window now so that we are deleted immediately and aren't left holding
@@ -3112,6 +3118,10 @@
           base::BindOnce(&BrowserView::OnFeatureEngagementTrackerInitialized,
                          weak_ptr_factory_.GetWeakPtr()));
 
+  paint_as_active_subscription_ =
+      GetWidget()->RegisterPaintAsActiveChangedCallback(base::BindRepeating(
+          &BrowserView::PaintAsActiveChanged, base::Unretained(this)));
+
   initialized_ = true;
 }
 
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index c030157..fb4455bf 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -839,6 +839,9 @@
   // whenever the touch mode changes.
   void MaybeShowReadingListInSidePanelIPH();
 
+  // Called when the widget's paint-as-active status changes.
+  void PaintAsActiveChanged();
+
   // The BrowserFrame that hosts this view.
   BrowserFrame* frame_ = nullptr;
 
@@ -1051,6 +1054,8 @@
   absl::optional<ui::ThroughputTracker> loading_animation_tracker_;
 #endif
 
+  base::CallbackListSubscription paint_as_active_subscription_;
+
   mutable base::WeakPtrFactory<BrowserView> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/ui/views/frame/contents_web_view.cc b/chrome/browser/ui/views/frame/contents_web_view.cc
index 7f88c3f0..68392d14 100644
--- a/chrome/browser/ui/views/frame/contents_web_view.cc
+++ b/chrome/browser/ui/views/frame/contents_web_view.cc
@@ -5,11 +5,14 @@
 #include "chrome/browser/ui/views/frame/contents_web_view.h"
 
 #include "chrome/browser/themes/theme_properties.h"
+#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/status_bubble_views.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/base/theme_provider.h"
+#include "ui/color/color_provider_utils.h"
 #include "ui/compositor/layer.h"
 #include "ui/compositor/layer_tree_owner.h"
 #include "ui/views/background.h"
@@ -19,10 +22,11 @@
 #include "ui/wm/core/window_util.h"
 #endif
 
-ContentsWebView::ContentsWebView(content::BrowserContext* browser_context)
+ContentsWebView::ContentsWebView(content::BrowserContext* browser_context,
+                                 const BrowserView* browser_view)
     : views::WebView(browser_context),
-      status_bubble_(nullptr) {
-}
+      status_bubble_(nullptr),
+      browser_view_(browser_view) {}
 
 ContentsWebView::~ContentsWebView() {
 }
@@ -64,13 +68,21 @@
   UpdateBackgroundColor();
 }
 
+void ContentsWebView::PaintAsActiveChanged() {
+  UpdateBackgroundColor();
+}
+
 void ContentsWebView::UpdateBackgroundColor() {
   const ui::ThemeProvider* const theme = GetThemeProvider();
   if (!theme)
     return;
 
-  const SkColor ntp_background = color_utils::GetResultingPaintColor(
-      theme->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND), SK_ColorWHITE);
+  const SkColor background = color_utils::GetResultingPaintColor(
+      theme->GetColor(web_contents() ? browser_view_->frame()
+                                           ->GetFrameView()
+                                           ->GetTabStripBackgroundColorId()
+                                     : ThemeProperties::COLOR_NTP_BACKGROUND),
+      SK_ColorWHITE);
   if (is_letterboxing()) {
     // Set the background color to a dark tint of the new tab page's background
     // color.  This is the color filled within the WebView's bounds when its
@@ -78,14 +90,14 @@
     // header file comments for more details.
     const int kBackgroundBrightness = 0x33;  // 20%
     // Make sure the background is opaque.
-    const SkColor dimmed_ntp_background = SkColorSetARGB(
-        SkColorGetA(ntp_background),
-        SkColorGetR(ntp_background) * kBackgroundBrightness / 0xFF,
-        SkColorGetG(ntp_background) * kBackgroundBrightness / 0xFF,
-        SkColorGetB(ntp_background) * kBackgroundBrightness / 0xFF);
-    SetBackground(views::CreateSolidBackground(dimmed_ntp_background));
+    const SkColor dimmed_background =
+        SkColorSetARGB(SkColorGetA(background),
+                       SkColorGetR(background) * kBackgroundBrightness / 0xFF,
+                       SkColorGetG(background) * kBackgroundBrightness / 0xFF,
+                       SkColorGetB(background) * kBackgroundBrightness / 0xFF);
+    SetBackground(views::CreateSolidBackground(dimmed_background));
   } else {
-    SetBackground(views::CreateSolidBackground(ntp_background));
+    SetBackground(views::CreateSolidBackground(background));
   }
   // Changing a view's background does not necessarily schedule the view to be
   // redrawn.
@@ -95,7 +107,7 @@
     content::RenderWidgetHostView* rwhv =
         web_contents()->GetRenderWidgetHostView();
     if (rwhv)
-      rwhv->SetBackgroundColor(ntp_background);
+      rwhv->SetBackgroundColor(background);
   }
 }
 
diff --git a/chrome/browser/ui/views/frame/contents_web_view.h b/chrome/browser/ui/views/frame/contents_web_view.h
index a81ac41..f344b781 100644
--- a/chrome/browser/ui/views/frame/contents_web_view.h
+++ b/chrome/browser/ui/views/frame/contents_web_view.h
@@ -13,6 +13,7 @@
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/views/controls/webview/webview.h"
 
+class BrowserView;
 class StatusBubbleViews;
 
 namespace ui {
@@ -25,7 +26,8 @@
       public WebContentsCloseHandlerDelegate {
  public:
   METADATA_HEADER(ContentsWebView);
-  explicit ContentsWebView(content::BrowserContext* browser_context);
+  ContentsWebView(content::BrowserContext* browser_context,
+                  const BrowserView* browser_view);
   ContentsWebView(const ContentsWebView&) = delete;
   ContentsWebView& operator=(const ContentsWebView&) = delete;
   ~ContentsWebView() override;
@@ -51,9 +53,13 @@
   void CloneWebContentsLayer() override;
   void DestroyClonedLayer() override;
 
+  // Called from BrowserView when its widget's paint-as-active status changes.
+  void PaintAsActiveChanged();
+
  private:
   void UpdateBackgroundColor();
   StatusBubbleViews* status_bubble_;
+  const BrowserView* const browser_view_;
 
   std::unique_ptr<ui::LayerTreeOwner> cloned_layer_tree_;
 };
diff --git a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
index e9ff57eb..3dc38bb 100644
--- a/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
+++ b/chrome/browser/ui/views/outdated_upgrade_bubble_view.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
+#include "base/strings/strcat.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "build/build_config.h"
@@ -16,6 +17,7 @@
 #include "chrome/browser/ui/views/chrome_typography.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #include "chrome/common/pref_names.h"
+#include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
@@ -35,17 +37,26 @@
 
 namespace {
 
-// The URL to be used to re-install Chrome when auto-update failed for too long.
-constexpr char kDownloadChromeUrl[] =
-    "https://www.google.com/chrome/?&brand=CHWL"
-    "&utm_campaign=en&utm_source=en-et-na-us-chrome-bubble&utm_medium=et";
-
 // The maximum number of ignored bubble we track in the NumLaterPerReinstall
 // histogram.
 constexpr int kMaxIgnored = 50;
 // The number of buckets we want the NumLaterPerReinstall histogram to use.
 constexpr int kNumIgnoredBuckets = 5;
 
+// For ChromeOS Lacros, browser updates are done via system services, thus
+// we redirect to the safetyCheck page that interacts with these. On other
+// platforms it may be possible to download an updated browser via a site.
+const char* kUpdateBrowserRedirectUrl =
+#if BUILDFLAG(IS_CHROMEOS_LACROS)
+    // The URL to be used to update Lacros-Chrome when auto-update failed
+    // for too long.
+    chrome::kChromeUIActivateSafetyCheckSettingsURL;
+#else
+    // The URL to be used to re-install Chrome when auto-update failed for
+    // too long.
+    "https://www.google.com/chrome";
+#endif
+
 bool g_upgrade_bubble_is_showing = false;
 
 // The number of times the user ignored the bubble before finally choosing to
@@ -62,7 +73,8 @@
 }
 
 void OnDialogAccepted(content::PageNavigator* navigator,
-                      bool auto_update_enabled) {
+                      bool auto_update_enabled,
+                      const char* update_browser_redirect_url) {
   // Offset the +1 in OnWindowClosing().
   --g_num_ignored_bubbles;
   if (auto_update_enabled) {
@@ -72,10 +84,11 @@
                                 kNumIgnoredBuckets);
     base::RecordAction(
         base::UserMetricsAction("OutdatedUpgradeBubble.Reinstall"));
-    navigator->OpenURL(
-        content::OpenURLParams(GURL(kDownloadChromeUrl), content::Referrer(),
-                               WindowOpenDisposition::NEW_FOREGROUND_TAB,
-                               ui::PAGE_TRANSITION_LINK, false));
+
+    navigator->OpenURL(content::OpenURLParams(
+        GURL(update_browser_redirect_url), content::Referrer(),
+        WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK,
+        false));
 #if defined(OS_WIN)
   } else {
     DCHECK(UpgradeDetector::GetInstance()->is_outdated_install_no_au());
@@ -117,7 +130,8 @@
       ui::DialogModel::Builder()
           .SetTitle(l10n_util::GetStringUTF16(IDS_UPGRADE_BUBBLE_TITLE))
           .AddOkButton(
-              base::BindOnce(&OnDialogAccepted, navigator, auto_update_enabled),
+              base::BindOnce(&OnDialogAccepted, navigator, auto_update_enabled,
+                             kUpdateBrowserRedirectUrl),
               l10n_util::GetStringUTF16(auto_update_enabled
                                             ? IDS_REINSTALL_APP
                                             : IDS_REENABLE_UPDATES))
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
index 1c3a675e..75eec17 100644
--- a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_action_button.cc
@@ -63,20 +63,9 @@
       action_name_for_metrics_(action_info.feature_name_for_metrics) {
   SetEnabled(true);
 
-  // This class wants to pretend to be a menu item visually, so it does its own
-  // hover effects by overriding LabelButton::UpdateBackgroundColor (below). It
-  // isn't sufficient to simply swap out the ink drop color - menu backgrounds
-  // are drawn below the text/icon but the ink drop would be drawn above them,
-  // which looks wrong.
-  // TODO(ellyjones): This removes ~all the benefit of being a HoverButton -
-  // should this class instead subclass LabelButton?
-
-  // TODO(crbug.com/1248181): Reverted to restore keyboard navigation showing
-  // background color highlights, but results in high-contrast mode using
-  // normal colors.
-  // views::InkDrop::Get(this)->SetMode(views::InkDropHost::InkDropMode::OFF);
-
   title()->SetTextContext(views::style::CONTEXT_MENU);
+  SetBackground(views::CreateThemedSolidBackground(
+      this, ui::NativeTheme::kColorId_MenuBackgroundColor));
 }
 
 SharingHubBubbleActionButton::~SharingHubBubbleActionButton() = default;
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
index 7a03b41..40f765998 100644
--- a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.cc
@@ -88,6 +88,14 @@
   views::BubbleDialogDelegateView::OnPaint(canvas);
 }
 
+void SharingHubBubbleViewImpl::OnThemeChanged() {
+  LocationBarBubbleDelegateView::OnThemeChanged();
+  if (GetWidget() && GetNativeTheme()) {
+    set_color(GetNativeTheme()->GetSystemColor(
+        ui::NativeTheme::kColorId_MenuBackgroundColor));
+  }
+}
+
 void SharingHubBubbleViewImpl::Show(DisplayReason reason) {
   ShowForReason(reason);
 }
@@ -116,6 +124,7 @@
 
   scroll_view_ = AddChildView(std::make_unique<views::ScrollView>());
   scroll_view_->ClipHeightTo(0, kActionButtonHeight * kMaximumButtons);
+  scroll_view_->SetBackgroundThemeColorId(ui::kColorMenuBackground);
 
   PopulateScrollView(controller_->GetFirstPartyActions(),
                      controller_->GetThirdPartyActions());
diff --git a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h
index d327709..91b39a69 100644
--- a/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h
+++ b/chrome/browser/ui/views/sharing_hub/sharing_hub_bubble_view_impl.h
@@ -49,6 +49,7 @@
   // LocationBarBubbleDelegateView:
   std::u16string GetAccessibleWindowTitle() const override;
   void OnPaint(gfx::Canvas* canvas) override;
+  void OnThemeChanged() override;
 
   // Shows the bubble view.
   void Show(DisplayReason reason);
diff --git a/chrome/browser/ui/views/toolbar/app_menu_browsertest.cc b/chrome/browser/ui/views/toolbar/app_menu_browsertest.cc
new file mode 100644
index 0000000..cfc7566e
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/app_menu_browsertest.cc
@@ -0,0 +1,65 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/callback_helpers.h"
+#include "base/files/file_path.h"
+#include "chrome/browser/sessions/tab_restore_service_factory.h"
+#include "chrome/browser/sessions/tab_restore_service_load_waiter.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/toolbar/browser_app_menu_button.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/test/browser_test.h"
+#include "ui/views/controls/menu/menu_runner.h"
+#include "url/gurl.h"
+
+using AppMenuBrowserTest = InProcessBrowserTest;
+
+namespace {
+
+bool TabRestoreServiceHasClosedWindow(sessions::TabRestoreService* service) {
+  for (const auto& entry : service->entries()) {
+    if (entry->type == sessions::TabRestoreService::WINDOW)
+      return true;
+  }
+  return false;
+}
+
+}  // namespace
+
+// This test shows the app-menu with a closed window added to the
+// TabRestoreService. This is a regression test to ensure menu code handles this
+// properly (this was triggering a crash in AppMenu where it was trying to make
+// use of RecentTabsMenuModelDelegate before created). See
+// https://crbug.com/1249741 for more.
+IN_PROC_BROWSER_TEST_F(AppMenuBrowserTest, ShowWithRecentlyClosedWindow) {
+  // Create an additional browser, close it, and ensure it is added to the
+  // TabRestoreService.
+  sessions::TabRestoreService* tab_restore_service =
+      TabRestoreServiceFactory::GetForProfile(browser()->profile());
+  TabRestoreServiceLoadWaiter tab_restore_service_load_waiter(
+      tab_restore_service);
+  tab_restore_service_load_waiter.Wait();
+  Browser* second_browser = CreateBrowser(browser()->profile());
+  content::WebContents* new_contents = chrome::AddSelectedTabWithURL(
+      second_browser,
+      ui_test_utils::GetTestUrl(base::FilePath(),
+                                base::FilePath().AppendASCII("simple.html")),
+      ui::PAGE_TRANSITION_TYPED);
+  EXPECT_TRUE(content::WaitForLoadStop(new_contents));
+  chrome::CloseWindow(second_browser);
+  ui_test_utils::WaitForBrowserToClose(second_browser);
+  EXPECT_TRUE(TabRestoreServiceHasClosedWindow(tab_restore_service));
+
+  // Show the AppMenu.
+  BrowserView::GetBrowserViewForBrowser(browser())
+      ->toolbar()
+      ->app_menu_button()
+      ->ShowMenu(views::MenuRunner::NO_FLAGS);
+}
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
index 798e00b..5820237 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button.cc
@@ -9,7 +9,6 @@
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/toolbar/chrome_labs_prefs.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
@@ -65,21 +64,6 @@
   new_experiments_indicator_->SetBoundsRect(dot_rect);
 }
 
-void ChromeLabsButton::OnThemeChanged() {
-  ToolbarButton::OnThemeChanged();
-
-  // We don't always have a theme provider (ui tests, for example).
-  const ui::ThemeProvider* theme_provider = GetThemeProvider();
-  if (!theme_provider)
-    return;
-
-  new_experiments_indicator_->SetColor(
-      /*dot_color=*/GetNativeTheme()->GetSystemColor(
-          ui::NativeTheme::kColorId_ProminentButtonColor),
-      /*border_color=*/theme_provider->GetColor(
-          ThemeProperties::COLOR_TOOLBAR));
-}
-
 void ChromeLabsButton::HideDotIndicator() {
   new_experiments_indicator_->Hide();
 }
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button.h b/chrome/browser/ui/views/toolbar/chrome_labs_button.h
index 0df8f54..411674b 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_button.h
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button.h
@@ -29,7 +29,6 @@
 
   // ToolbarButton:
   void Layout() override;
-  void OnThemeChanged() override;
 
   void HideDotIndicator();
 
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
index 4f04b5d..9e0ba19 100644
--- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
+++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -141,10 +141,6 @@
           std::make_unique<AuthenticatorAndroidAccessorySheetModel>(
               dialog_model));
       break;
-    case Step::kCableV2Activate:
-      sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
-          std::make_unique<AuthenticatorPaaskV2SheetModel>(dialog_model));
-      break;
     case Step::kCableV2QRCode:
       sheet_view = std::make_unique<AuthenticatorQRSheetView>(
           std::make_unique<AuthenticatorQRSheetModel>(dialog_model));
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index a202572..53f622e 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -637,59 +637,6 @@
   return other_mechanisms_menu_model_.get();
 }
 
-// AuthenticatorPaaskV2SheetModel  -----------------------------------------
-
-AuthenticatorPaaskV2SheetModel::AuthenticatorPaaskV2SheetModel(
-    AuthenticatorRequestDialogModel* dialog_model)
-    : AuthenticatorSheetModelBase(dialog_model),
-      other_mechanisms_menu_model_(
-          std::make_unique<OtherMechanismsMenuModel>(dialog_model)) {}
-
-AuthenticatorPaaskV2SheetModel::~AuthenticatorPaaskV2SheetModel() = default;
-
-bool AuthenticatorPaaskV2SheetModel::IsBackButtonVisible() const {
-  return true;
-}
-
-bool AuthenticatorPaaskV2SheetModel::IsActivityIndicatorVisible() const {
-  return true;
-}
-
-const gfx::VectorIcon& AuthenticatorPaaskV2SheetModel::GetStepIllustration(
-    ImageColorScheme color_scheme) const {
-  return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
-                                                 : kWebauthnPhoneIcon;
-}
-
-bool AuthenticatorPaaskV2SheetModel::IsAcceptButtonVisible() const {
-  return true;
-}
-
-bool AuthenticatorPaaskV2SheetModel::IsAcceptButtonEnabled() const {
-  return true;
-}
-
-std::u16string AuthenticatorPaaskV2SheetModel::GetAcceptButtonLabel() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_TITLE);
-}
-
-void AuthenticatorPaaskV2SheetModel::OnAccept() {
-  return dialog_model()->StartPhonePairing();
-}
-
-std::u16string AuthenticatorPaaskV2SheetModel::GetStepTitle() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_V2_ACTIVATE_TITLE);
-}
-
-std::u16string AuthenticatorPaaskV2SheetModel::GetStepDescription() const {
-  return l10n_util::GetStringUTF16(
-      IDS_WEBAUTHN_CABLE_V2_ACTIVATE_DESCRIPTION_SHORT);
-}
-
-ui::MenuModel* AuthenticatorPaaskV2SheetModel::GetOtherMechanismsMenuModel() {
-  return other_mechanisms_menu_model_.get();
-}
-
 // AuthenticatorClientPinEntrySheetModel
 // -----------------------------------------
 
@@ -1232,9 +1179,11 @@
 }
 
 std::u16string AuthenticatorQRSheetModel::GetStepTitle() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_TITLE);
+  // TODO: i18n once final strings are ready.
+  return u"Use your phone";
 }
 
 std::u16string AuthenticatorQRSheetModel::GetStepDescription() const {
-  return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_DESCRIPTION);
+  // TODO: i18n once final strings are ready.
+  return u"Scan this QR Code with your Android phone.";
 }
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h
index 63c98406..0b0cab1 100644
--- a/chrome/browser/ui/webauthn/sheet_models.h
+++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -291,29 +291,6 @@
   std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
 };
 
-class AuthenticatorPaaskV2SheetModel : public AuthenticatorSheetModelBase {
- public:
-  explicit AuthenticatorPaaskV2SheetModel(
-      AuthenticatorRequestDialogModel* dialog_model);
-  ~AuthenticatorPaaskV2SheetModel() override;
-
- private:
-  // AuthenticatorSheetModelBase:
-  bool IsBackButtonVisible() const override;
-  bool IsActivityIndicatorVisible() const override;
-  const gfx::VectorIcon& GetStepIllustration(
-      ImageColorScheme color_scheme) const override;
-  std::u16string GetStepTitle() const override;
-  std::u16string GetStepDescription() const override;
-  ui::MenuModel* GetOtherMechanismsMenuModel() override;
-  bool IsAcceptButtonVisible() const override;
-  bool IsAcceptButtonEnabled() const override;
-  std::u16string GetAcceptButtonLabel() const override;
-  void OnAccept() override;
-
-  std::unique_ptr<OtherMechanismsMenuModel> other_mechanisms_menu_model_;
-};
-
 class AuthenticatorClientPinEntrySheetModel
     : public AuthenticatorSheetModelBase {
  public:
diff --git a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
index cbdbe14..aae4153e26 100644
--- a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
@@ -9,8 +9,8 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
 #include "chrome/browser/ash/arc/arc_util.h"
-#include "chrome/browser/ash/full_restore/full_restore_service_factory.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_features.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_pref_names.h"
 #include "chrome/browser/ash/plugin_vm/plugin_vm_util.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/people_section.cc b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
index 6418875..7469a33 100644
--- a/chrome/browser/ui/webui/settings/chromeos/people_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/people_section.cc
@@ -613,11 +613,6 @@
   };
   html_source->AddLocalizedStrings(kLocalizedStrings);
 
-  // TODO(https://crbug.com/1227694): Remove this after migrating all JS usages
-  // of splitSettingsSyncEnabled to syncSettingsCategorizationEnabled and
-  // syncConsentOptionalEnabled.
-  html_source->AddBoolean("splitSettingsSyncEnabled",
-                          chromeos::features::IsSplitSettingsSyncEnabled());
   html_source->AddBoolean(
       "syncSettingsCategorizationEnabled",
       chromeos::features::IsSyncSettingsCategorizationEnabled());
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 5e84941..fbf5dc6dd 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -294,7 +294,7 @@
       "preinstalled_web_apps/youtube.h",
     ]
 
-    if (is_chromeos_ash) {
+    if (is_chromeos) {
       sources += [
         "preinstalled_web_apps/calculator.cc",
         "preinstalled_web_apps/calculator.h",
diff --git a/chrome/browser/web_applications/preinstalled_web_app_manager.cc b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
index 40c35d11..05ddeae 100644
--- a/chrome/browser/web_applications/preinstalled_web_app_manager.cc
+++ b/chrome/browser/web_applications/preinstalled_web_app_manager.cc
@@ -491,7 +491,7 @@
 
     options.require_manifest = true;
 
-#if !BUILDFLAG(IS_CHROMEOS_ASH)
+#if !defined(OS_CHROMEOS)
     if (!g_bypass_offline_manifest_requirement_for_testing_) {
       // Non-Chrome OS platforms are not permitted to fetch the web app install
       // URLs during start up.
@@ -506,7 +506,7 @@
     options.add_to_management = false;
     options.add_to_desktop = false;
     options.add_to_quick_launch_bar = false;
-#endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // !defined(OS_CHROMEOS)
   }
 
   // TODO(crbug.com/1175196): Move this constant into some shared constants.h
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/calculator.cc b/chrome/browser/web_applications/preinstalled_web_apps/calculator.cc
index 22a82920..5f8010f5 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/calculator.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/calculator.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/preinstalled_app_install_features.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h"
 #include "chrome/browser/web_applications/web_application_info.h"
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc b/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
index 409cae7..0fbde90e 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/gmail.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/preinstalled_app_install_features.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h"
 #include "chrome/browser/web_applications/web_application_info.h"
@@ -18,11 +17,11 @@
   ExternalInstallOptions options(
       /*install_url=*/GURL(
           "https://mail.google.com/mail/installwebapp?usp=chrome_default"),
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
       /*user_display_mode=*/DisplayMode::kStandalone,
 #else
       /*user_display_mode=*/DisplayMode::kBrowser,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // defined(OS_CHROMEOS)
       /*install_source=*/ExternalInstallSource::kExternalDefault);
 
   options.user_type_allowlist = {"unmanaged", "managed", "child"};
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
index 5dd20247..f50c31f 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_calendar.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/preinstalled_app_install_features.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h"
 #include "chrome/browser/web_applications/web_application_info.h"
@@ -101,11 +100,11 @@
   ExternalInstallOptions options(
       /*install_url=*/GURL("https://calendar.google.com/calendar/"
                            "installwebapp?usp=chrome_default"),
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
       /*user_display_mode=*/DisplayMode::kStandalone,
 #else
       /*user_display_mode=*/DisplayMode::kBrowser,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // defined(OS_CHROMEOS)
       /*install_source=*/ExternalInstallSource::kExternalDefault);
 
   options.user_type_allowlist = {"unmanaged", "managed", "child"};
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc b/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
index 97e63ad..1687072 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/google_drive.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
-#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/preinstalled_app_install_features.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h"
 #include "chrome/browser/web_applications/web_application_info.h"
@@ -105,11 +104,11 @@
   ExternalInstallOptions options(
       /*install_url=*/GURL(
           "https://drive.google.com/drive/installwebapp?usp=chrome_default"),
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
       /*user_display_mode=*/DisplayMode::kStandalone,
 #else
       /*user_display_mode=*/DisplayMode::kBrowser,
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // defined(OS_CHROMEOS)
       /*install_source=*/ExternalInstallSource::kExternalDefault);
 
   options.user_type_allowlist = {"unmanaged", "managed", "child"};
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
index e31d0c239..7687011 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
@@ -7,7 +7,6 @@
 #include "base/command_line.h"
 #include "build/branding_buildflags.h"
 #include "build/buildflag.h"
-#include "build/chromeos_buildflags.h"
 #include "chrome/browser/web_applications/web_app_constants.h"
 #include "chrome/common/chrome_switches.h"
 
@@ -19,12 +18,12 @@
 #include "chrome/browser/web_applications/preinstalled_web_apps/google_slides.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/youtube.h"
 
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
 #include "chrome/browser/web_applications/preinstalled_web_apps/calculator.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/google_calendar.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/google_chat.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/google_meet.h"
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // defined(OS_CHROMEOS)
 
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
@@ -63,12 +62,12 @@
       GetConfigForGoogleSheets(),
       GetConfigForGoogleSlides(),
       GetConfigForYouTube(),
-#if BUILDFLAG(IS_CHROMEOS_ASH)
+#if defined(OS_CHROMEOS)
       GetConfigForCalculator(),
       GetConfigForGoogleCalendar(),
       GetConfigForGoogleChat(),
       GetConfigForGoogleMeet(),
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
+#endif  // defined(OS_CHROMEOS)
       // clang-format on
   };
 #else
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 95f5eac..be479a47 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -246,30 +246,19 @@
 }
 
 void AuthenticatorRequestDialogModel::
-    EnsureBleAdapterIsPoweredAndContinueWithCable() {
+    EnsureBleAdapterIsPoweredAndContinueWithStep(Step step) {
   DCHECK(current_step() == Step::kMechanismSelection ||
          current_step() == Step::kUsbInsertAndActivate ||
          current_step() == Step::kCableActivate ||
          current_step() == Step::kAndroidAccessory ||
          current_step() == Step::kOffTheRecordInterstitial ||
          current_step() == Step::kNotStarted);
-  Step cable_step;
-  if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
-    // caBLEv1/2 without QR codes.
-    cable_step = Step::kCableActivate;
-  } else {
-    // caBLEv2 with QR support. Display QR code if the user never paired a phone
-    // before, or show instructions how to use the previously paired phone
-    // otherwise. The user can still decide to pair a new phone on that screen.
-    cable_step =
-        paired_phones_.empty() ? Step::kCableV2QRCode : Step::kCableV2Activate;
-  }
   if (ble_adapter_is_powered()) {
-    SetCurrentStep(cable_step);
+    SetCurrentStep(step);
     return;
   }
 
-  next_step_once_ble_powered_ = cable_step;
+  next_step_once_ble_powered_ = step;
   SetCurrentStep(transport_availability()->can_power_on_ble_adapter
                      ? Step::kBlePowerOnAutomatic
                      : Step::kBlePowerOnManual);
@@ -724,7 +713,7 @@
       StartPlatformAuthenticatorFlow();
       break;
     case AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy:
-      EnsureBleAdapterIsPoweredAndContinueWithCable();
+      EnsureBleAdapterIsPoweredAndContinueWithStep(Step::kCableActivate);
       break;
     case AuthenticatorTransport::kAndroidAccessory:
       SetCurrentStep(Step::kAndroidAccessory);
@@ -734,6 +723,12 @@
   }
 }
 
+void AuthenticatorRequestDialogModel::StartGuidedFlowForOtherPhone(
+    size_t mechanism_index) {
+  current_mechanism_ = mechanism_index;
+  EnsureBleAdapterIsPoweredAndContinueWithStep(Step::kCableV2QRCode);
+}
+
 void AuthenticatorRequestDialogModel::StartWinNativeApi(
     size_t mechanism_index) {
   DCHECK(transport_availability_.has_win_native_api_authenticator);
@@ -769,7 +764,7 @@
 void AuthenticatorRequestDialogModel::ContactPhoneAfterOffTheRecordInterstitial(
     std::string name) {
   ContactNextPhoneByName(name);
-  EnsureBleAdapterIsPoweredAndContinueWithCable();
+  EnsureBleAdapterIsPoweredAndContinueWithStep(Step::kCableActivate);
 }
 
 void AuthenticatorRequestDialogModel::StartLocationBarBubbleRequest() {
@@ -847,13 +842,18 @@
       AuthenticatorTransport::kInternal,
   };
 
+  const auto kCable = AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy;
+  bool include_other_phone_mechanism = false;
+
   if (cable_ui_type_) {
     switch (*cable_ui_type_) {
       case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR:
-        if (!base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport)) {
-          break;
+        if (base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport) &&
+            base::Contains(transport_availability_.available_transports,
+                           kCable)) {
+          include_other_phone_mechanism = true;
         }
-        [[fallthrough]];
+        break;
 
       case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
         transports_to_list_if_active.push_back(
@@ -861,24 +861,19 @@
         [[fallthrough]];
 
       case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1: {
-        const auto cable =
-            AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy;
         if (base::Contains(transport_availability_.available_transports,
-                           cable)) {
-          transports_to_list_if_active.push_back(cable);
+                           kCable)) {
+          transports_to_list_if_active.push_back(kCable);
           DCHECK(is_get_assertion ||
                  base::FeatureList::IsEnabled(device::kWebAuthPhoneSupport));
           if (!priority_transport) {
-            priority_transport = cable;
+            priority_transport = kCable;
           }
 
           // If this is a caBLEv1 or server-link request then offering to "Try
           // Again" is unfortunate because the server won't send another ping
           // to the phone. It is valid if trying to use USB devices but the
           // confusion of the caBLE case overrides that.
-          //
-          // The only other case here is device::kWebAuthPhoneSupport mode,
-          // which is purely for testing so we don't worry about it.
           offer_try_again_in_ui_ = false;
         }
         break;
@@ -916,9 +911,7 @@
         !priority_transport.has_value() && paired_phones_.empty());
   }
 
-  if (base::Contains(
-          transport_availability_.available_transports,
-          AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy)) {
+  if (base::Contains(transport_availability_.available_transports, kCable)) {
     for (const auto& phone_name : paired_phone_names()) {
       const std::u16string name16 = base::UTF8ToUTF16(phone_name);
       static constexpr size_t kMaxLongNameChars = 50;
@@ -935,6 +928,19 @@
                               mechanisms_.size()),
           /*priority=*/false);
     }
+
+    if (include_other_phone_mechanism) {
+      // TODO(agl): i18n once final strings are ready.
+      const std::u16string label =
+          paired_phones_.empty() ? u"Your phone" : u"Another phone";
+
+      mechanisms_.emplace_back(
+          Mechanism::OtherPhone(), label, label, GetTransportIcon(kCable),
+          base::BindRepeating(
+              &AuthenticatorRequestDialogModel::StartGuidedFlowForOtherPhone,
+              base::Unretained(this), mechanisms_.size()),
+          /*is_priority=*/false);
+    }
   }
 
   // At most one mechanism has priority.
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index 5196c4a..3048716 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -92,7 +92,6 @@
     // Phone as a security key.
     kCableActivate,
     kAndroidAccessory,
-    kCableV2Activate,
     kCableV2QRCode,
 
     // Authenticator Client PIN.
@@ -158,7 +157,9 @@
     using WindowsAPI = base::StrongAlias<class WindowsAPITag,
                                          bool /* unused, but cannot be void */>;
     using Phone = base::StrongAlias<class PhoneTag, std::string>;
-    using Type = absl::variant<Transport, WindowsAPI, Phone>;
+    using OtherPhone = base::StrongAlias<class OtherPhoneTag,
+                                         bool /* unused, but cannot be void */>;
+    using Type = absl::variant<Transport, WindowsAPI, Phone, OtherPhone>;
 
     Mechanism(Type type,
               std::u16string name,
@@ -303,7 +304,7 @@
   // Valid action when at step: kNotStarted, kMechanismSelection, and steps
   // where the other transports menu is shown, namely, kUsbInsertAndActivate,
   // kCableActivate.
-  void EnsureBleAdapterIsPoweredAndContinueWithCable();
+  void EnsureBleAdapterIsPoweredAndContinueWithStep(Step step);
 
   // Continues with the BLE/caBLE flow now that the Bluetooth adapter is
   // powered.
@@ -570,6 +571,9 @@
   void StartGuidedFlowForTransport(AuthenticatorTransport transport,
                                    size_t mechanism_index);
 
+  // Starts the flow for adding an unlisted phone by showing a QR code.
+  void StartGuidedFlowForOtherPhone(size_t mechanism_index);
+
   // Displays a resident-key warning if needed and then calls
   // |HideDialogAndDispatchToNativeWindowsApi|.
   void StartWinNativeApi(size_t mechanism_index);
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index f922510d..f40b443 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1632138958-ef07b020a796747831f7743236e22c5f6fe6d35d.profdata
+chrome-mac-main-1632160516-0572ef449c8e21593aff64b60346242b4c12a3a2.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 03c63c73..657a89b 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1632128335-e00e6ef17919fdaf71d1c9acf4d1d609b14f8b3e.profdata
+chrome-win32-main-1632157255-b0f6e01f989b2114ad66786e49fba1eef0d94598.profdata
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 35ba5fec..74ef7c6c 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -21,6 +21,8 @@
 
 const char kChromeUIAboutHost[] = "about";
 const char kChromeUIAboutURL[] = "chrome://about/";
+const char kChromeUIActivateSafetyCheckSettingsURL[] =
+    "chrome://settings/safetyCheck?activateSafetyCheck";
 const char kChromeUIAccessibilityHost[] = "accessibility";
 const char kChromeUIAllSitesPath[] = "/content/all";
 const char kChromeUIAppIconHost[] = "app-icon";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index 578b1cc0..f04fff8 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -29,6 +29,7 @@
 // Please keep in alphabetical order, with OS/feature specific sections below.
 extern const char kChromeUIAboutHost[];
 extern const char kChromeUIAboutURL[];
+extern const char kChromeUIActivateSafetyCheckSettingsURL[];
 extern const char kChromeUIAccessibilityHost[];
 extern const char kChromeUIAllSitesPath[];
 extern const char kChromeUIAppIconHost[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 12cc26fe..e898713 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2008,6 +2008,7 @@
       "../browser/ui/views/tab_search_bubble_host_browsertest.cc",
       "../browser/ui/views/tabs/tab_search_button_browsertest.cc",
       "../browser/ui/views/tabs/tab_strip_browsertest.cc",
+      "../browser/ui/views/toolbar/app_menu_browsertest.cc",
       "../browser/ui/views/toolbar/avatar_toolbar_button_browsertest.cc",
       "../browser/ui/views/toolbar/chrome_labs_browsertest.cc",
       "../browser/ui/views/web_apps/frame_toolbar/web_app_frame_toolbar_browsertest.cc",
@@ -3006,6 +3007,7 @@
         "../browser/ash/app_mode/kiosk_app_update_service_browsertest.cc",
         "../browser/ash/app_mode/kiosk_crash_restore_browsertest.cc",
         "../browser/ash/app_mode/web_app/web_kiosk_app_data_browsertest.cc",
+        "../browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc",
         "../browser/ash/apps/apk_web_app_installer_browsertest.cc",
         "../browser/ash/arc/accessibility/arc_accessibility_helper_bridge_browsertest.cc",
         "../browser/ash/arc/auth/arc_active_directory_enrollment_token_fetcher_browsertest.cc",
@@ -3053,7 +3055,6 @@
         "../browser/ash/file_manager/image_loader_jstest.cc",
         "../browser/ash/file_manager/video_player_jstest.cc",
         "../browser/ash/first_run/drive_first_run_browsertest.cc",
-        "../browser/ash/full_restore/full_restore_app_launch_handler_browsertest.cc",
         "../browser/ash/input_method/input_method_engine_browsertests.cc",
         "../browser/ash/input_method/native_input_method_engine_browsertest.cc",
         "../browser/ash/input_method/textinput_browsertest.cc",
@@ -3488,7 +3489,6 @@
         "//ash/keyboard/ui:resources",
         "//chrome",
         "//chrome/test/data/webui/cr_components/chromeos/cellular_setup:modulize_runtime_data",
-        "//chrome/test/data/webui/cr_components/chromeos/network_health:modulize_runtime_data",
         "//chrome/test/data/webui/nearby_share/shared:modulize_runtime_data",
         "//chrome/test/data/webui/settings/chromeos:modulize_runtime_data",
         "//testing/buildbot/filters:chromeos_filters",
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 2b2c109..f8b136c 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -102,7 +102,7 @@
 #include "ash/public/cpp/test/shell_test_api.h"
 #include "ash/shell.h"
 #include "base/system/sys_info.h"
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
 #include "chrome/browser/ash/input_method/input_method_configuration.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
 #include "chromeos/services/device_sync/device_sync_impl.h"
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index a23d7dd..d00ca256 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -25,7 +25,7 @@
 #endif
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-#include "chrome/browser/ash/full_restore/full_restore_app_launch_handler.h"
+#include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h"
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 namespace base {
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index cbc06164..923d7776 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -385,6 +385,7 @@
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_people_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_privacy_page_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_settings_menu_test.m.js",
+        "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_sync_controls_optional_disabled_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/lock_screen_tests.m.js",
         "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_printing_page_tests.m.js",
diff --git a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
index be61f8c0..7e93362 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
@@ -36,6 +36,7 @@
     ":overview_card_test",
     ":percent_bar_chart_test",
     ":realtime_cpu_chart_test",
+    ":routine_group_test",
     ":routine_list_executor_test",
     ":routine_result_entry_test",
     ":routine_result_list_test",
@@ -54,6 +55,7 @@
     "//ash/webui/diagnostics_ui/resources:battery_status_card",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_section",
     "//ui/webui/resources/js:load_time_data.m",
   ]
@@ -127,10 +129,12 @@
     "//ash/webui/diagnostics_ui/resources:battery_status_card",
     "//ash/webui/diagnostics_ui/resources:cpu_card",
     "//ash/webui/diagnostics_ui/resources:data_point",
+    "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
     "//ash/webui/diagnostics_ui/resources:memory_card",
     "//ash/webui/diagnostics_ui/resources:percent_bar_chart",
     "//ash/webui/diagnostics_ui/resources:realtime_cpu_chart",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_result_entry",
     "//ash/webui/diagnostics_ui/resources:routine_result_list",
     "//ash/webui/diagnostics_ui/resources:routine_section",
@@ -309,6 +313,16 @@
   ]
 }
 
+js_library("routine_group_test") {
+  deps = [
+    "../..:chai_assert",
+    "//ash/webui/diagnostics_ui/resources:diagnostics_types",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
+    "//ash/webui/diagnostics_ui/resources:routine_list_executor",
+    "//ash/webui/diagnostics_ui/resources:routine_result_entry",
+  ]
+}
+
 js_library("routine_list_executor_test") {
   deps = [
     "../..:chai_assert",
@@ -325,6 +339,7 @@
     "../..:test_util",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_list_executor",
     "//ash/webui/diagnostics_ui/resources:routine_result_entry",
   ]
@@ -337,6 +352,7 @@
     "../..:test_util",
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_list_executor",
     "//ash/webui/diagnostics_ui/resources:routine_result_entry",
     "//ash/webui/diagnostics_ui/resources:routine_result_list",
@@ -351,6 +367,7 @@
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_system_routine_controller",
     "//ash/webui/diagnostics_ui/resources:mojo_interface_provider",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_list_executor",
     "//ash/webui/diagnostics_ui/resources:routine_result_entry",
     "//ash/webui/diagnostics_ui/resources:routine_section",
@@ -368,6 +385,7 @@
     "//ash/webui/diagnostics_ui/resources:diagnostics_types",
     "//ash/webui/diagnostics_ui/resources:fake_data",
     "//ash/webui/diagnostics_ui/resources:fake_system_data_provider",
+    "//ash/webui/diagnostics_ui/resources:routine_group",
     "//ash/webui/diagnostics_ui/resources:routine_list_executor",
     "//ash/webui/diagnostics_ui/resources:system_page",
   ]
diff --git a/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
index 564aa995..6d03864 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/cellular_info_test.js
@@ -25,7 +25,10 @@
     cellularInfoElement = null;
   });
 
-  function initializeCellularInfo() {
+  /**
+   * @param {!Network} network
+   */
+  function initializeCellularInfo(network) {
     assertFalse(!!cellularInfoElement);
 
     // Add the cellular info to the DOM.
@@ -33,14 +36,31 @@
         /** @type {!CellularInfoElement} */ (
             document.createElement('cellular-info'));
     assertTrue(!!cellularInfoElement);
-    cellularInfoElement.network = fakeCellularNetwork;
+    cellularInfoElement.network = network;
     document.body.appendChild(cellularInfoElement);
 
     return flushTasks();
   }
 
+  /**
+   * Forces update to cellular network technology.
+   * @param {string} networkTechnology
+   * @return {!Promise}
+   */
+  function setNetworkTechnology(networkTechnology) {
+    assertTrue(!!cellularInfoElement);
+
+    const cellularTypeProps = Object.assign(
+        {}, fakeCellularNetwork.typeProperties.cellular, {networkTechnology});
+    cellularInfoElement.network = Object.assign(
+        {}, fakeCellularNetwork,
+        {typeProperties: {cellular: cellularTypeProps}});
+
+    return flushTasks();
+  }
+
   test('CellularInfoPopulated', () => {
-    return initializeCellularInfo().then(() => {
+    return initializeCellularInfo(fakeCellularNetwork).then(() => {
       assertDataPointHasExpectedHeaderAndValue(
           cellularInfoElement, '#ipAddress',
           cellularInfoElement.i18n('networkIpAddressLabel'),
@@ -74,4 +94,79 @@
           `${fakeCellularNetwork.typeProperties.cellular.eid}`);
     });
   });
+
+  test('CellularNetworkTechnologyTranslated', () => {
+    return initializeCellularInfo()
+        .then(() => setNetworkTechnology('CDMA1XRTT'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyCdma1xrttLabel')))
+        .then(() => setNetworkTechnology('EDGE'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyEdgeLabel')))
+        .then(() => setNetworkTechnology('EVDO'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyEvdoLabel')))
+        .then(() => setNetworkTechnology('GPRS'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyGprsLabel')))
+        .then(() => setNetworkTechnology('GSM'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyGsmLabel')))
+        .then(() => setNetworkTechnology('HSPA'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyHspaLabel')))
+        .then(() => setNetworkTechnology('HSPAPlus'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyHspaPlusLabel')))
+        .then(() => setNetworkTechnology('LTE'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyLteLabel')))
+        .then(() => setNetworkTechnology('LTEAdvanced'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyLteAdvancedLabel')))
+        .then(() => setNetworkTechnology('UMTS'))
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'),
+                cellularInfoElement.i18n('networkTechnologyUmtsLabel')))
+        // When typeProperties have not been set yet display empty string.
+        .then(() => {
+          assertTrue(!!cellularInfoElement);
+          cellularInfoElement.network =
+              Object.assign({}, fakeCellularNetwork, {typeProperties: null});
+          return flushTasks();
+        })
+        .then(
+            () => assertDataPointHasExpectedHeaderAndValue(
+                cellularInfoElement, '#technology',
+                cellularInfoElement.i18n('networkTechnologyLabel'), ''));
+  });
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
index c6759ee7..65eb43a 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/connectivity_card_test.js
@@ -9,6 +9,7 @@
 import {FakeNetworkHealthProvider} from 'chrome://diagnostics/fake_network_health_provider.js';
 import {FakeSystemRoutineController} from 'chrome://diagnostics/fake_system_routine_controller.js';
 import {setNetworkHealthProviderForTesting, setSystemRoutineControllerForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
+import {RoutineGroup} from 'chrome://diagnostics/routine_group.js';
 import {TestSuiteStatus} from 'chrome://diagnostics/routine_list_executor.js';
 
 import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
@@ -27,12 +28,16 @@
   let routineController;
 
   /** @type {!Array<!RoutineType>} */
-  const defaultRoutineOverride = [RoutineType.kCaptivePortal];
+  const defaultRoutineOverride = [new RoutineGroup(
+      [RoutineType.kCaptivePortal], 'captivePortalRoutineText')];
 
   suiteSetup(() => {
     provider = new FakeNetworkHealthProvider();
     setNetworkHealthProviderForTesting(provider);
+  });
 
+  setup(() => {
+    document.body.innerHTML = '';
     // Setup a fake routine controller.
     routineController = new FakeSystemRoutineController();
     routineController.setDelayTimeInMillisecondsForTesting(-1);
@@ -51,10 +56,6 @@
     setSystemRoutineControllerForTesting(routineController);
   });
 
-  setup(() => {
-    document.body.innerHTML = '';
-  });
-
   teardown(() => {
     connectivityCardElement.remove();
     connectivityCardElement = null;
@@ -85,7 +86,12 @@
    */
   function getRoutines() {
     assertTrue(!!connectivityCardElement);
-    return connectivityCardElement.routines_;
+    let routines = [];
+    for (let routineGroup of connectivityCardElement.routineGroups_) {
+      routines = [...routines, ...routineGroup.routines];
+    }
+
+    return routines;
   }
 
   /**
@@ -116,7 +122,6 @@
     assertTrue(!!connectivityCardElement);
     const routineSection = dx_utils.getRoutineSection(connectivityCardElement);
     routineSection.routines = routines;
-    routineSection.runTestsAutomatically = true;
   }
 
   /**
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
index 2963de7..78446b3 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_app_unified_test.js
@@ -29,6 +29,7 @@
 import {overviewCardTestSuite} from './overview_card_test.js';
 import {percentBarChartTestSuite} from './percent_bar_chart_test.js';
 import {realtimeCpuChartTestSuite} from './realtime_cpu_chart_test.js';
+import {routineGroupTestSuite} from './routine_group_test.js';
 import {fakeRoutineListExecutorTestSuite} from './routine_list_executor_test.js';
 import {routineResultEntryTestSuite} from './routine_result_entry_test.js';
 import {routineResultListTestSuite} from './routine_result_list_test.js';
@@ -75,6 +76,7 @@
 runSuite('OverviewCard', overviewCardTestSuite);
 runSuite('PercentBarChart', percentBarChartTestSuite);
 runSuite('RealtimeCpuChart', realtimeCpuChartTestSuite);
+runSuite('RoutineGroup', routineGroupTestSuite, 'network');
 runSuite('RoutineListExecutor', fakeRoutineListExecutorTestSuite);
 runSuite('RoutineResultEntry', routineResultEntryTestSuite);
 runSuite('RoutineResultList', routineResultListTestSuite);
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
index e33bada3..f5041a0 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_browsertest.js
@@ -103,6 +103,7 @@
   'OverviewCard',
   'PercentBarChart',
   'RealtimeCpuChart',
+  'RoutineGroup',
   'RoutineListExecutor',
   'RoutineResultEntry',
   'RoutineResultList',
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
index 1d220a14..62cceb4 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_utils_test.js
@@ -3,10 +3,11 @@
 // found in the LICENSE file.
 
 import {NetworkType, RoutineType} from 'chrome://diagnostics/diagnostics_types.js';
-import {convertKibToGibDecimalString, getRoutinesByNetworkType, getSubnetMaskFromRoutingPrefix} from 'chrome://diagnostics/diagnostics_utils.js';
+import {convertKibToGibDecimalString, getRoutineGroups, getSubnetMaskFromRoutingPrefix} from 'chrome://diagnostics/diagnostics_utils.js';
+import {RoutineGroup} from 'chrome://diagnostics/routine_group.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
-import {assertArrayEquals, assertEquals} from '../../chai_assert.js';
+import {assertArrayEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 
 export function diagnosticsUtilsTestSuite() {
   test('ProperlyConvertsKibToGib', () => {
@@ -57,52 +58,53 @@
     assertEquals(getSubnetMaskFromRoutingPrefix(32), '255.255.255.255');
   });
 
-  test('GetRoutinesByNetworkType', () => {
+  test('AllRoutineGroupsPresent', () => {
     loadTimeData.overrideValues({enableArcNetworkDiagnostics: true});
+    let isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics');
+    let routineGroups = getRoutineGroups(NetworkType.kWiFi, isArcEnabled);
 
-    /** @type {!Array<!RoutineType>} */
-    const expectedRoutinesWifi = [
-      RoutineType.kCaptivePortal,
-      RoutineType.kDnsLatency,
-      RoutineType.kDnsResolution,
-      RoutineType.kDnsResolverPresent,
-      RoutineType.kGatewayCanBePinged,
-      RoutineType.kHttpFirewall,
-      RoutineType.kHttpsFirewall,
-      RoutineType.kHttpsLatency,
-      RoutineType.kLanConnectivity,
-      RoutineType.kArcHttp,
-      RoutineType.kArcPing,
-      RoutineType.kArcDnsResolution,
-      // assertArrayEquals wants values in order, code appends values to end
-      // of array.
-      RoutineType.kHasSecureWiFiConnection,
-      RoutineType.kSignalStrength,
-    ];
+    // All groups should be present.
+    assertEquals(routineGroups.length, 4);
 
-    /** @type {!Array<!RoutineType>} */
-    const expectedRoutinesNotWifi = [
-      RoutineType.kCaptivePortal,
-      RoutineType.kDnsLatency,
-      RoutineType.kDnsResolution,
-      RoutineType.kDnsResolverPresent,
-      RoutineType.kGatewayCanBePinged,
-      RoutineType.kHttpFirewall,
-      RoutineType.kHttpsFirewall,
-      RoutineType.kHttpsLatency,
-      RoutineType.kLanConnectivity,
-      RoutineType.kArcHttp,
-      RoutineType.kArcPing,
-      RoutineType.kArcDnsResolution,
-    ];
+    // WiFi group should exist and all three WiFi routines should be present.
+    let wifiGroup = routineGroups[2];
+    assertEquals(wifiGroup.routines.length, 3);
+    assertEquals(wifiGroup.groupName, 'wifiGroupLabel');
 
-    assertArrayEquals(
-        expectedRoutinesWifi, getRoutinesByNetworkType(NetworkType.kWiFi));
-    assertArrayEquals(
-        expectedRoutinesNotWifi,
-        getRoutinesByNetworkType(NetworkType.kEthernet));
-    assertArrayEquals(
-        expectedRoutinesNotWifi,
-        getRoutinesByNetworkType(NetworkType.kCellular));
+    // ARC routines should be present in their categories.
+    let nameResolutionGroup = routineGroups[1];
+    assertTrue(
+        nameResolutionGroup.routines.includes(RoutineType.kArcDnsResolution));
+
+    let internetConnectivityGroup = routineGroups[3];
+    assertTrue(
+        internetConnectivityGroup.routines.includes(RoutineType.kArcPing));
+    assertTrue(
+        internetConnectivityGroup.routines.includes(RoutineType.kArcHttp));
+  });
+
+  test('NetworkTypeIsNotWiFi', () => {
+    let isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics');
+    let routineGroups = getRoutineGroups(NetworkType.kEthernet, isArcEnabled);
+    // WiFi group should be missing.
+    assertEquals(routineGroups.length, 3);
+    let groupNames = routineGroups.map(group => group.groupName);
+    assertFalse(groupNames.includes('wifiGroupLabel'));
+  });
+
+  test('ArcRoutinesDisabled', () => {
+    loadTimeData.overrideValues({enableArcNetworkDiagnostics: false});
+    let isArcEnabled = loadTimeData.getBoolean('enableArcNetworkDiagnostics');
+    let routineGroups = getRoutineGroups(NetworkType.kEthernet, isArcEnabled);
+
+    let nameResolutionGroup = routineGroups[1];
+    assertFalse(
+        nameResolutionGroup.routines.includes(RoutineType.kArcDnsResolution));
+
+    let internetConnectivityGroup = routineGroups[2];
+    assertFalse(
+        internetConnectivityGroup.routines.includes(RoutineType.kArcPing));
+    assertFalse(
+        internetConnectivityGroup.routines.includes(RoutineType.kArcHttp));
   });
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js b/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
index a1362ab..52d693d 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/ethernet_info_test.js
@@ -25,7 +25,10 @@
     ethernetInfoElement = null;
   });
 
-  function initializeEthernetInfo() {
+  /**
+   * @param {!Network} network
+   */
+  function initializeEthernetInfo(network) {
     assertFalse(!!ethernetInfoElement);
 
     // Add the ethernet info to the DOM.
@@ -33,7 +36,7 @@
         /** @type {!EthernetInfoElement} */ (
             document.createElement('ethernet-info'));
     assertTrue(!!ethernetInfoElement);
-    ethernetInfoElement.network = fakeEthernetNetwork;
+    ethernetInfoElement.network = network;
     document.body.appendChild(ethernetInfoElement);
 
     return flushTasks();
@@ -47,16 +50,16 @@
     const baseProperties = {
       authentication: AuthenticationType.kNone,
     };
-    const ethernetTypeProperties = Object.assign({}, baseProperties, typeProps);
+    const ethernetTypeProperies = Object.assign({}, baseProperties, typeProps);
     return Object.assign({}, fakeEthernetNetwork, {
       typeProperties: {
-        ethernet: ethernetTypeProperties,
+        ethernet: ethernetTypeProperies,
       }
     });
   }
 
   test('EthernetInfoPopulated', () => {
-    return initializeEthernetInfo().then(() => {
+    return initializeEthernetInfo(fakeEthernetNetwork).then(() => {
       // Element expected on screen but data currently missing in api.
       // TODO(ashleydp): Update test when link speed data-point value provided.
       assertTextContains(
@@ -65,7 +68,7 @@
   });
 
   test('EthernetInfoIpAddressBasedOnNetwork', () => {
-    return initializeEthernetInfo().then(() => {
+    return initializeEthernetInfo(fakeEthernetNetwork).then(() => {
       const expectedHeader = ethernetInfoElement.i18n('networkIpAddressLabel');
       assertDataPointHasExpectedHeaderAndValue(
           ethernetInfoElement, '#ipAddress', expectedHeader,
@@ -73,7 +76,7 @@
     });
   });
 
-  test('EthernetInfoAuthenticationWithAuthentication8021x', () => {
+  test('EthernetInfoAuthenticationBasedOnNetwork', () => {
     return initializeEthernetInfo(fakeEthernetNetwork).then(() => {
       const expectedHeader =
           ethernetInfoElement.i18n('networkAuthenticationLabel');
@@ -85,14 +88,11 @@
     });
   });
 
-  test('EthernetInfoAuthenticationWithAuthenticationNone', () => {
-    return initializeEthernetInfo()
-        .then(() => {
-          ethernetInfoElement.network = getEthernetNetworkWithTypeProperties(
-              /** @type {EthernetStateProperties} */
-              ({authentication: AuthenticationType.kNone}));
-          return flushTasks();
-        })
+  test('EthernetInfoAuthenticationWithAuthentication', () => {
+    return initializeEthernetInfo(
+               getEthernetNetworkWithTypeProperties(
+                   /** @type {EthernetStateProperties} */
+                   ({authentication: AuthenticationType.kNone})))
         .then(() => {
           const expectedHeader =
               ethernetInfoElement.i18n('networkAuthenticationLabel');
diff --git a/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js b/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
index b6c407e..b276c08 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/network_card_test.js
@@ -4,7 +4,7 @@
 
 import 'chrome://diagnostics/network_card.js';
 
-import {fakeCellularNetwork, fakeDisconnectedEthernetNetwork, fakeDisconnectedWifiNetwork, fakeEthernetNetwork, fakeNetworkGuidInfoList, fakeWifiNetwork, fakeWifiNetworkDisabled} from 'chrome://diagnostics/fake_data.js';
+import {fakeCellularNetwork, fakeDisconnectedEthernetNetwork, fakeDisconnectedWifiNetwork, fakeEthernetNetwork, fakeNetworkGuidInfoList, fakePortalWifiNetwork, fakeWifiNetwork, fakeWifiNetworkDisabled} from 'chrome://diagnostics/fake_data.js';
 import {FakeNetworkHealthProvider} from 'chrome://diagnostics/fake_network_health_provider.js';
 import {setNetworkHealthProviderForTesting} from 'chrome://diagnostics/mojo_interface_provider.js';
 
@@ -49,6 +49,7 @@
         'ethernetDisconnectedGuid', [fakeDisconnectedEthernetNetwork]);
     provider.setFakeNetworkState(
         'wifiDisconnectedGuid', [fakeDisconnectedWifiNetwork]);
+    provider.setFakeNetworkState('wifiPortalGuid', [fakePortalWifiNetwork]);
     // Add the network info to the DOM.
     networkCardElement = /** @type {!NetworkCardElement} */ (
         document.createElement('network-card'));
@@ -67,12 +68,45 @@
         networkCardElement.$$('#networkTroubleshooting'));
   }
 
+  /** @return {!Element} */
+  function getIpConfigDrawerElement() {
+    assertTrue(!!networkCardElement);
+
+    return /** @type {!Element} */ (
+        networkCardElement.$$('#ipConfigInfoDrawer'));
+  }
+
+  /** @return {!Element} */
+  function getNetworkInfoElement() {
+    assertTrue(!!networkCardElement);
+
+    return /** @type {!Element} */ (networkCardElement.$$('network-info'));
+  }
+
+  /** @return {!Element} */
+  function getEthernetInfoElement() {
+    const networkInfoElement = getNetworkInfoElement();
+    assertTrue(!!networkInfoElement);
+
+    return dx_utils.getEthernetInfoElement(networkInfoElement);
+  }
+
+  /** @return {!Element} */
+  function getWifiInfoElement() {
+    const networkInfoElement = getNetworkInfoElement();
+    assertTrue(!!networkInfoElement);
+
+    return dx_utils.getWifiInfoElement(networkInfoElement);
+  }
+
   test('CardTitleWiFiConnectedInitializedCorrectly', () => {
     return initializeNetworkCard('wifiGuid').then(() => {
       dx_utils.assertElementContainsText(
           networkCardElement.$$('#cardTitle'),
           'Wi-Fi [84:C5:A6:30:3F:31] (Connected)');
       assertFalse(isVisible(getTroubleConnectingElement()));
+      assertTrue(isVisible(getWifiInfoElement()));
+      assertTrue(isVisible(getIpConfigDrawerElement()));
     });
   });
 
@@ -82,6 +116,8 @@
           networkCardElement.$$('#cardTitle'),
           'Wi-Fi [84:C5:A6:30:3F:31] (Disabled)');
       assertTrue(isVisible(getTroubleConnectingElement()));
+      assertFalse(isVisible(getNetworkInfoElement()));
+      assertFalse(isVisible(getIpConfigDrawerElement()));
     });
   });
 
@@ -91,6 +127,19 @@
           networkCardElement.$$('#cardTitle'),
           'Wi-Fi [84:C5:A6:30:3F:31] (Not Connected)');
       assertTrue(isVisible(getTroubleConnectingElement()));
+      assertFalse(isVisible(getNetworkInfoElement()));
+      assertFalse(isVisible(getIpConfigDrawerElement()));
+    });
+  });
+
+  test('WifiPortalShowTroubleShooting', () => {
+    return initializeNetworkCard('wifiPortalGuid').then(() => {
+      dx_utils.assertElementContainsText(
+          networkCardElement.$$('#cardTitle'),
+          'Wi-Fi [84:C5:A6:30:3F:31] (Portal)');
+      assertTrue(isVisible(getTroubleConnectingElement()));
+      assertTrue(isVisible(getNetworkInfoElement()));
+      assertTrue(isVisible(getIpConfigDrawerElement()));
     });
   });
 
@@ -100,6 +149,7 @@
           networkCardElement.$$('#cardTitle'),
           'Ethernet [81:C5:A6:30:3F:31] (Online)');
       assertFalse(isVisible(getTroubleConnectingElement()));
+      assertTrue(isVisible(getEthernetInfoElement()));
     });
   });
 
@@ -109,6 +159,8 @@
           networkCardElement.$$('#cardTitle'),
           'Ethernet [81:C5:A6:30:3F:32] (Not Connected)');
       assertTrue(isVisible(getTroubleConnectingElement()));
+      assertFalse(isVisible(getNetworkInfoElement()));
+      assertFalse(isVisible(getIpConfigDrawerElement()));
     });
   });
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js
new file mode 100644
index 0000000..c0cc107
--- /dev/null
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_group_test.js
@@ -0,0 +1,105 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {RoutineResult, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/diagnostics_types.js';
+import {RoutineGroup} from 'chrome://diagnostics/routine_group.js';
+import {ExecutionProgress, ResultStatusItem} from 'chrome://diagnostics/routine_list_executor.js';
+import {getRoutineType} from 'chrome://diagnostics/routine_result_entry.js';
+
+import {assertEquals} from '../../chai_assert.js';
+
+/**
+ * @param {!RoutineType} routineType
+ * @return {!ResultStatusItem}
+ */
+function getRoutineRunningStatusItem(routineType) {
+  return new ResultStatusItem(routineType, ExecutionProgress.kRunning);
+}
+
+/**
+ * @param {!RoutineType} routineType
+ * @return {!ResultStatusItem}
+ */
+function getRoutinedPassedStatusItem(routineType) {
+  let item = new ResultStatusItem(routineType, ExecutionProgress.kCompleted);
+  item.result = /** @type {!RoutineResult} */ (
+      {simpleResult: StandardRoutineResult.kTestPassed});
+  return item;
+}
+
+/**
+ * @param {!RoutineType} routineType
+ * @return {!ResultStatusItem}
+ */
+function getRoutinedFailedStatusItem(routineType) {
+  let item = new ResultStatusItem(routineType, ExecutionProgress.kCompleted);
+  item.result = /** @type {!RoutineResult} */ (
+      {simpleResult: StandardRoutineResult.kTestFailed});
+  return item;
+}
+
+export function routineGroupTestSuite() {
+  const {kSignalStrength, kHasSecureWiFiConnection} = RoutineType;
+  test('GroupStatusSetCorrectly', () => {
+    let routineGroup = new RoutineGroup(
+        [
+          kSignalStrength,
+          kHasSecureWiFiConnection,
+        ],
+        'wifiGroupText');
+
+    let signalStrengthRunning = getRoutineRunningStatusItem(kSignalStrength);
+    let signalStrengthCompleted = getRoutinedPassedStatusItem(kSignalStrength);
+
+    // Progress is initially "Not started".
+    assertEquals(routineGroup.progress, ExecutionProgress.kNotStarted);
+
+    // Progress should now be running since the signal strength test is in
+    // progress.
+    routineGroup.setStatus(signalStrengthRunning);
+    assertEquals(routineGroup.progress, ExecutionProgress.kRunning);
+
+    // Progress should still be running despite the signal strength test
+    // finishing since their are still unfinished routines in this group.
+    routineGroup.setStatus(signalStrengthCompleted);
+    assertEquals(routineGroup.progress, ExecutionProgress.kRunning);
+
+    let hasSecureWiFiConnectionRunning =
+        getRoutineRunningStatusItem(kHasSecureWiFiConnection);
+    let hasSecureWiFiConnectionCompleted =
+        getRoutinedPassedStatusItem(kHasSecureWiFiConnection);
+
+    // Progress should still be running.
+    routineGroup.setStatus(hasSecureWiFiConnectionRunning);
+    assertEquals(routineGroup.progress, ExecutionProgress.kRunning);
+
+    // Status should be completed now that all routines in this group
+    // have finished running.
+    routineGroup.setStatus(hasSecureWiFiConnectionCompleted);
+    assertEquals(routineGroup.progress, ExecutionProgress.kCompleted);
+  });
+
+  test('TestFailureHandledCorrectly', () => {
+    let routineGroup = new RoutineGroup(
+        [
+          kSignalStrength,
+          kHasSecureWiFiConnection,
+        ],
+        'wifiGroupText');
+
+    let signalStrengthFailed = getRoutinedFailedStatusItem(kSignalStrength);
+
+    routineGroup.setStatus(signalStrengthFailed);
+    assertEquals(routineGroup.failedTest, getRoutineType(kSignalStrength));
+
+    let hasSecureWiFiConnectionFailed =
+        getRoutinedFailedStatusItem(kHasSecureWiFiConnection);
+    routineGroup.setStatus(hasSecureWiFiConnectionFailed);
+
+    // Failed test does not get overwritten.
+    // TODO(michaelcheco): Update when change is made to cancel remaining tests
+    // after a failure is encountered.
+    assertEquals(routineGroup.failedTest, getRoutineType(kSignalStrength));
+  });
+}
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index 6c9eb71..c320376b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -5,6 +5,7 @@
 import 'chrome://diagnostics/routine_result_entry.js';
 
 import {RoutineResult, RoutineType, StandardRoutineResult} from 'chrome://diagnostics/diagnostics_types.js';
+import {RoutineGroup} from 'chrome://diagnostics/routine_group.js';
 import {ExecutionProgress, ResultStatusItem} from 'chrome://diagnostics/routine_list_executor.js';
 import {BadgeType} from 'chrome://diagnostics/text_badge.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
@@ -29,7 +30,8 @@
     routineResultEntryElement = null;
   });
 
-  function initializeRoutineResultEntry() {
+  /** @param {boolean=} usingRoutineGroups */
+  function initializeRoutineResultEntry(usingRoutineGroups = false) {
     assertFalse(!!routineResultEntryElement);
 
     // Add the entry to the DOM.
@@ -37,13 +39,13 @@
         document.createElement('routine-result-entry'));
     assertTrue(!!routineResultEntryElement);
     document.body.appendChild(routineResultEntryElement);
-
+    routineResultEntryElement.usingRoutineGroups = usingRoutineGroups;
     return flushTasks();
   }
 
   /**
    * Updates the item in the element.
-   * @param {!ResultStatusItem} item
+   * @param {ResultStatusItem|RoutineGroup} item
    * @return {!Promise}
    */
   function updateItem(item) {
@@ -53,11 +55,12 @@
 
   /**
    * Initializes the entry then updates the item.
-   * @param {!ResultStatusItem} item
+   * @param {ResultStatusItem|RoutineGroup} item
+   * @param {boolean=} usingRoutineGroups
    * @return {!Promise}
    */
-  function initializeEntryWithItem(item) {
-    return initializeRoutineResultEntry().then(() => {
+  function initializeEntryWithItem(item, usingRoutineGroups = false) {
+    return initializeRoutineResultEntry(usingRoutineGroups).then(() => {
       return updateItem(item);
     });
   }
@@ -244,13 +247,10 @@
   });
 
   test('RoutineHasLinkTest', () => {
-    const item = createCompletedStatus(
-        RoutineType.kLanConnectivity,
-        /** @type {!RoutineResult} */ ({
-          simpleResult: StandardRoutineResult.kTestPassed
-        }));
+    const item = new RoutineGroup(
+        [RoutineType.kLanConnectivity], 'lanConnectivityRoutineText');
 
-    return initializeEntryWithItem(item).then(() => {
+    return initializeEntryWithItem(item, true).then(() => {
       // Span should not be hidden
       assertTrue(isVisible(getRoutineLinkContainer()));
     });
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
index b9d8bed..16bb178 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/fake_shimless_rma_service_test.js
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {fakeCalibrationComponents} from 'chrome://shimless-rma/fake_data.js';
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
 import {CalibrationComponentStatus, CalibrationObserverRemote, CalibrationOverallStatus, CalibrationSetupInstruction, CalibrationStatus, ComponentRepairStatus, ComponentType, ErrorObserverRemote, HardwareWriteProtectionStateObserverRemote, OsUpdateObserverRemote, OsUpdateOperation, PowerCableStateObserverRemote, ProvisioningObserverRemote, ProvisioningStep, RmadErrorCode, RmaState} from 'chrome://shimless-rma/shimless_rma_types.js';
 
@@ -661,7 +662,7 @@
         CalibrationSetupInstruction
             .kCalibrationInstructionPlaceBaseOnFlatSurface);
 
-    return service.startCalibration().then((state) => {
+    return service.startCalibration(fakeCalibrationComponents).then((state) => {
       assertEquals(state.state, RmaState.kChooseDestination);
       assertEquals(state.error, RmadErrorCode.kOk);
     });
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_page_test.js
index 193aae6..9d4b945 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/reimaging_calibration_page_test.js
@@ -3,12 +3,13 @@
 // found in the LICENSE file.
 
 import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js';
+import {fakeCalibrationComponents} from 'chrome://shimless-rma/fake_data.js';
 import {FakeShimlessRmaService} from 'chrome://shimless-rma/fake_shimless_rma_service.js';
 import {setShimlessRmaServiceForTesting} from 'chrome://shimless-rma/mojo_interface_provider.js';
 import {ReimagingCalibrationPageElement} from 'chrome://shimless-rma/reimaging_calibration_page.js';
-import {CalibrationComponentStatus, CalibrationStatus, ComponentType} from 'chrome://shimless-rma/shimless_rma_types.js';
+import {CalibrationComponentStatus, CalibrationStatus} from 'chrome://shimless-rma/shimless_rma_types.js';
 
-import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {assertDeepEquals, assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.js';
 
 export function reimagingCalibrationPageTest() {
@@ -35,79 +36,132 @@
 
   /**
    * @return {!Promise}
-   * @param {!ComponentType} repairedComponent
+   * @param {!Array<!CalibrationComponentStatus>} calibrationComponents
    */
-  function initializeCalibrationPage(repairedComponent) {
+  function initializeCalibrationPage(calibrationComponents) {
     assertFalse(!!component);
 
+    // Initialize the fake data.
+    service.setGetCalibrationComponentListResult(calibrationComponents);
+
     component = /** @type {!ReimagingCalibrationPageElement} */ (
         document.createElement('reimaging-calibration-page'));
     assertTrue(!!component);
-    component.repairedComponent = repairedComponent;
     document.body.appendChild(component);
 
     return flushTasks();
   }
 
+  /**
+   * @return {!Promise}
+   */
+  function clickComponentCameraToggle() {
+    const cameraComponent =
+        component.shadowRoot.querySelector('#componentCamera');
+    assertFalse(cameraComponent.disabled);
+    cameraComponent.click();
+    return flushTasks();
+  }
+
+  /**
+   * Get getComponentsList_ private member for testing.
+   * @suppress {visibility} // access private member
+   * @return {!Array<!CalibrationComponentStatus>}
+   */
+  function getComponentsList() {
+    return component.getComponentsList_();
+  }
+
+  /**
+   * @param {!Array<!CalibrationComponentStatus>} components
+   * @return {!Array<!CalibrationComponentStatus>}
+   */
+  function getExpectedComponentsList(components) {
+    /** @type {!Array<!CalibrationComponentStatus>} */
+    let expectedComponents = [];
+    components.forEach(componentStatus => {
+      let status = componentStatus.status;
+      if (status === CalibrationStatus.kCalibrationFailed) {
+        status = CalibrationStatus.kCalibrationWaiting;
+      }
+      expectedComponents.push({
+        component: componentStatus.component,
+        status: status,
+        progress: 0.0
+      });
+    });
+    return expectedComponents;
+  }
+
+
   test('Initializes', async () => {
-    await initializeCalibrationPage(ComponentType.kBaseAccelerometer);
-    const preCalibration =
-        component.shadowRoot.querySelector('#preCalibration');
-    const Calibration = component.shadowRoot.querySelector('#calibration');
-    assertTrue(Calibration.hidden);
-    assertFalse(preCalibration.hidden);
+    await initializeCalibrationPage(fakeCalibrationComponents);
+
+    const cameraComponent =
+        component.shadowRoot.querySelector('#componentCamera');
+    const batteryComponent =
+        component.shadowRoot.querySelector('#componentBattery');
+    const baseAccelerometerComponent =
+        component.shadowRoot.querySelector('#componentBaseAccelerometer');
+    const lidAccelerometerComponent =
+        component.shadowRoot.querySelector('#componentLidAccelerometer');
+    const touchpadComponent =
+        component.shadowRoot.querySelector('#componentTouchpad');
+    assertEquals('Camera', cameraComponent.componentName);
+    assertFalse(cameraComponent.disabled);
+    assertFalse(cameraComponent.skip);
+    assertFalse(cameraComponent.completed);
+    assertEquals('Battery', batteryComponent.componentName);
+    assertTrue(batteryComponent.disabled);
+    assertFalse(batteryComponent.skip);
+    assertTrue(batteryComponent.completed);
+    assertEquals(
+        'Base Accelerometer', baseAccelerometerComponent.componentName);
+    assertTrue(baseAccelerometerComponent.disabled);
+    assertFalse(baseAccelerometerComponent.skip);
+    assertFalse(baseAccelerometerComponent.completed);
+    assertEquals('Lid Accelerometer', lidAccelerometerComponent.componentName);
+    assertFalse(lidAccelerometerComponent.disabled);
+    assertFalse(lidAccelerometerComponent.skip);
+    assertFalse(lidAccelerometerComponent.completed);
+    assertEquals('Touchpad', touchpadComponent.componentName);
+    assertFalse(touchpadComponent.disabled);
+    assertTrue(touchpadComponent.skip);
+    assertFalse(touchpadComponent.completed);
+  });
+
+  test('ToggleComponent', async () => {
+    await initializeCalibrationPage(fakeCalibrationComponents);
+    await clickComponentCameraToggle();
+    let expectedComponents =
+        getExpectedComponentsList(fakeCalibrationComponents);
+    let components = getComponentsList();
+    assertNotEquals(expectedComponents, components);
+    // Camera should be the first entry in the list.
+    expectedComponents[0].status = CalibrationStatus.kCalibrationSkip;
+    assertDeepEquals(expectedComponents, components);
   });
 
   test('NextButtonTriggersCalibration', async () => {
-    await initializeCalibrationPage(ComponentType.kBaseAccelerometer);
-    component.onNextButtonClick().catch((err) => void 0);
+    const resolver = new PromiseResolver();
+    await initializeCalibrationPage(fakeCalibrationComponents);
+    let expectedComponents =
+        getExpectedComponentsList(fakeCalibrationComponents);
+    let startCalibrationCalls = 0;
+    service.startCalibration = (components) => {
+      assertDeepEquals(expectedComponents, components);
+      startCalibrationCalls++;
+      return resolver.promise;
+    };
 
-    const preCalibration =
-        component.shadowRoot.querySelector('#preCalibration');
-    const Calibration = component.shadowRoot.querySelector('#calibration');
-    assertFalse(Calibration.hidden);
-    assertTrue(preCalibration.hidden);
-  });
-
-  test('CalibrationComplete', async () => {
-    await initializeCalibrationPage(ComponentType.kLidAccelerometer);
-    component.onNextButtonClick().catch((err) => void 0);
-    await flushTasks();
-
-    service.triggerCalibrationObserver(
-        /** @type {!CalibrationComponentStatus} */
-        ({
-          component: ComponentType.kLidAccelerometer,
-          status: CalibrationStatus.kCalibrationComplete,
-          progress: 1.0
-        }),
-        0);
-    await flushTasks();
-
+    let expectedResult = {foo: 'bar'};
     let savedResult;
-    let savedError;
-    component.onNextButtonClick()
-        .then((result) => savedResult = result)
-        .catch((error) => savedError = error);
+    component.onNextButtonClick().then((result) => savedResult = result);
+    // Resolve to a distinct result to confirm it was not modified.
+    resolver.resolve(expectedResult);
     await flushTasks();
 
-    assertTrue(!!savedResult);
-  });
-
-  test('CalibrationInProgress', async () => {
-    await initializeCalibrationPage(ComponentType.kGyroscope);
-    component.onNextButtonClick().catch((err) => void 0);
-    await flushTasks();
-
-    let savedResult;
-    let savedError;
-    component.onNextButtonClick()
-        .then((result) => savedResult = result)
-        .catch((error) => savedError = error);
-    await flushTasks();
-
-    assertTrue(savedError instanceof Error);
-    assertEquals(savedError.message, 'Calibration is not complete.');
-    assertEquals(savedResult, undefined);
+    assertEquals(1, startCalibrationCalls);
+    assertDeepEquals(expectedResult, savedResult);
   });
 }
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
index 4fc8c54..350705a6 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_browsertest.js
@@ -55,6 +55,7 @@
   'ReimagingProvisioningPageTest',
   'ShimlessRMAAppTest',
   'WrapupRepairCompletePageTest',
+  'WrapupRestockPageTest',
 ];
 
 TEST_F('ShimlessRMABrowserTest', 'All', function() {
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_unified_test.js b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_unified_test.js
index 3330b34b..482e4ba 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_unified_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/shimless_rma_unified_test.js
@@ -20,6 +20,7 @@
 import {reimagingProvisioningPageTest} from './reimaging_provisioning_page_test.js';
 import {shimlessRMAAppTest} from './shimless_rma_app_test.js';
 import {wrapupRepairCompletePageTest} from './wrapup_repair_complete_page_test.js';
+import {wrapupRestockPageTest} from './wrapup_restock_page_test.js';
 
 window.test_suites_list = [];
 
@@ -54,3 +55,4 @@
 runSuite('ReimagingProvisioningPageTest', reimagingProvisioningPageTest);
 runSuite('ShimlessRMAAppTest', shimlessRMAAppTest);
 runSuite('WrapupRepairCompletePageTest', wrapupRepairCompletePageTest);
+runSuite('WrapupRestockPageTest', wrapupRestockPageTest);
diff --git a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
index 1a35aa8..75e35932 100644
--- a/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
+++ b/chrome/test/data/webui/chromeos/shimless_rma/wrapup_restock_page_test.js
@@ -46,6 +46,16 @@
     return flushTasks();
   }
 
+  /**
+   * @return {!Promise}
+   */
+  function clickShutdownButton() {
+    const shutdownComponent = component.shadowRoot.querySelector('#shutdown');
+    assertTrue(!!shutdownComponent);
+    shutdownComponent.click();
+    return flushTasks();
+  }
+
   test('ComponentRenders', async () => {
     await initializeRestockPage();
     assertTrue(!!component);
@@ -70,27 +80,21 @@
     resolver.resolve(expectedResult);
     await flushTasks();
 
-    assertEquals(callCounter, 1);
-    assertDeepEquals(savedResult, expectedResult);
+    assertEquals(1, callCounter);
+    assertDeepEquals(expectedResult, savedResult);
   });
 
   test('RestockPageOnShutdownCallsShutdownForRestock', async () => {
     const resolver = new PromiseResolver();
     await initializeRestockPage();
-    let callCounter = 0;
+    let restockCallCounter = 0;
     service.shutdownForRestock = () => {
-      callCounter++;
+      restockCallCounter++;
       return resolver.promise;
     };
 
-    let expectedResult = {foo: 'bar'};
-    let savedResult;
-    component.onNextButtonClick().then((result) => savedResult = result);
-    // Resolve to a distinct result to confirm it was not modified.
-    resolver.resolve(expectedResult);
-    await flushTasks();
+    await clickShutdownButton();
 
-    assertEquals(callCounter, 1);
-    assertDeepEquals(savedResult, expectedResult);
+    assertEquals(1, restockCallCounter);
   });
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
index 260d1460..3c6a418 100644
--- a/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/BUILD.gn
@@ -11,11 +11,13 @@
     "cellular_setup:modulize",
     "multidevice_setup:modulize",
     "network:modulize",
-    "network_health:modulize",
     "//chrome/test/data/webui/chromeos:modulize",
   ]
 }
 
 group("closure_compile") {
-  deps = [ "bluetooth:closure_compile" ]
+  deps = [
+    "bluetooth:closure_compile",
+    "network_health:closure_compile",
+  ]
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
index a284dfd..b823968 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cr_components_chromeos_v3_browsertest.js
@@ -46,7 +46,7 @@
  ['SimLockDialogs', 'network/sim_lock_dialogs_test.m.js'],
 ].forEach(test => registerTest('NetworkComponents', 'os-settings', ...test));
 
-[['RoutineGroup', 'network_health/routine_group_test.m.js'],
+[['RoutineGroup', 'network_health/routine_group_test.js'],
 ].forEach(test => registerTest('NetworkHealth', 'connectivity-diagnostics', ...test));
 
 [
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn b/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
index 4d7899a..01b735a 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/BUILD.gn
@@ -5,14 +5,22 @@
 import("//third_party/closure_compiler/compile_js.gni")
 import("//ui/webui/resources/tools/js_modulizer.gni")
 
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  closure_flags = default_closure_args + [ "browser_resolver_prefix_replacements=\"chrome://connectivity-diagnostics/=../../chromeos/components/connectivity_diagnostics/resources/\"" ]
+  deps = [ ":routine_group_test" ]
+}
+
 js_library("routine_group_test") {
   deps = [
+    ":network_health_test_utils",
     "../../..:chai_assert",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/cr_components/chromeos/network_health:network_diagnostics.m",
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
 }
 
-js_modulizer("modulize") {
-  input_files = [ "routine_group_test.js" ]
+js_library("network_health_test_utils") {
+  deps = [ "//ui/webui/resources/cr_components/chromeos/network_health:network_diagnostics.m" ]
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/network_health_test_utils.js b/chrome/test/data/webui/cr_components/chromeos/network_health/network_health_test_utils.js
new file mode 100644
index 0000000..e8a0e96
--- /dev/null
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/network_health_test_utils.js
@@ -0,0 +1,31 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
+import 'chrome://resources/mojo/chromeos/services/network_health/public/mojom/network_diagnostics.mojom-lite.js';
+
+/**
+ * Removes any prefixed URL from a icon image path
+ * @param {string} src
+ * @return {string}
+ */
+export function getIconFromSrc(src) {
+  const values = src.split('/');
+  return values[values.length - 1];
+}
+
+/**
+ * Creates and returns a basic RoutineResult structure
+ * @param {!chromeos.networkDiagnostics.mojom.RoutineVerdict} verdict
+ * @return {!chromeos.networkDiagnostics.mojom.RoutineResult}
+ */
+export function createResult(verdict) {
+  return {
+    verdict: verdict,
+    problems: {},
+    timestamp: {
+      internalValue: BigInt(0),
+    },
+  };
+}
diff --git a/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js b/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
index 2a3778a..8df6f80e 100644
--- a/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/network_health/routine_group_test.js
@@ -2,15 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// clang-format off
-// #import 'chrome://connectivity-diagnostics/strings.m.js';
-// #import 'chrome://resources/cr_components/chromeos/network_health/network_diagnostics_mojo.m.js'
-// #import {Routine, Icons} from 'chrome://resources/cr_components/chromeos/network_health/network_diagnostics_types.m.js'
-// #import 'chrome://resources/cr_components/chromeos/network_health/routine_group.m.js'
-// #import {assertTrue, assertFalse, assertEquals} from '../../../chai_assert.js';
+import 'chrome://connectivity-diagnostics/strings.m.js';
+import 'chrome://resources/cr_components/chromeos/network_health/network_diagnostics_mojo.m.js';
+import 'chrome://resources/cr_components/chromeos/network_health/routine_group.m.js';
 
-// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-// clang-format on
+import {Icons, Routine} from 'chrome://resources/cr_components/chromeos/network_health/network_diagnostics_types.m.js';
+import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js';
+
+import {createResult, getIconFromSrc} from './network_health_test_utils.js';
 
 /**
  * Creates baseline routines.
@@ -25,9 +26,8 @@
       resultMsg: 'Passed',
       group: 0,
       type: 0,
-      result: {
-        verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem
-      },
+      result: createResult(
+          chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem),
       ariaDescription: '',
     },
     {
@@ -36,26 +36,14 @@
       resultMsg: 'Passed',
       group: 0,
       type: 1,
-      result: {
-        verdict: chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem
-      },
+      result: createResult(
+          chromeos.networkDiagnostics.mojom.RoutineVerdict.kNoProblem),
       ariaDescription: '',
     }
   ];
 }
 
 /**
- * Removes any prefixed URL from a icon image path
- * @param {string}
- * @return {string}
- * @private
- */
-function getIconFromSrc(src) {
-  const values = src.split('/');
-  return values[values.length - 1];
-}
-
-/**
  * Test suite for the Routine Group element.
  */
 suite('RoutineGroupTest', function routineGroupTest() {
@@ -69,7 +57,7 @@
     routineGroup.name = 'Group';
     routineGroup.expanded = false;
     document.body.appendChild(routineGroup);
-    Polymer.dom.flush();
+    flush();
   });
 
   teardown(function() {
@@ -84,18 +72,17 @@
    */
   function setRoutines(routines) {
     routineGroup.routines = routines;
-    Polymer.dom.flush();
+    flush();
   }
 
   /**
    * Clicks the routine group container to toggle the expanded state.
-   * @param {boolean} expanded
    */
   function clickRoutineGroup() {
     const container = routineGroup.$$('network-health-container');
     assertTrue(!!container);
     container.click();
-    Polymer.dom.flush();
+    flush();
   }
 
   /**
@@ -158,7 +145,7 @@
    */
   test('RunningNone', () => {
     routineGroup.routines = createRoutines();
-    Polymer.dom.flush();
+    flush();
 
     checkResult(Icons.TEST_PASSED);
     clickRoutineGroup();
@@ -170,9 +157,8 @@
   test('FailedOne', () => {
     let routines = createRoutines();
     routines[0].resultMsg = 'Failed';
-    routines[0].result = {
-      'verdict': chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem
-    };
+    routines[0].result =
+        createResult(chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem);
     setRoutines(routines);
     checkResult(Icons.TEST_FAILED);
     clickRoutineGroup();
@@ -184,9 +170,8 @@
   test('NotRunOne', () => {
     let routines = createRoutines();
     routines[0].resultMsg = 'Not Run';
-    routines[0].result = {
-      'verdict': chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun
-    };
+    routines[0].result =
+        createResult(chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun);
     setRoutines(routines);
     checkResult(Icons.TEST_NOT_RUN);
     clickRoutineGroup();
@@ -198,13 +183,11 @@
   test('NotRunAndFailed', () => {
     let routines = createRoutines();
     routines[0].resultMsg = 'Not Run';
-    routines[0].result = {
-      'verdict': chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun
-    };
+    routines[0].result =
+        createResult(chromeos.networkDiagnostics.mojom.RoutineVerdict.kNotRun);
     routines[1].resultMsg = 'Failed';
-    routines[1].result = {
-      'verdict': chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem
-    };
+    routines[1].result =
+        createResult(chromeos.networkDiagnostics.mojom.RoutineVerdict.kProblem);
     setRoutines(routines);
     checkResult(Icons.TEST_FAILED);
     clickRoutineGroup();
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_cros_interactive_test.js b/chrome/test/data/webui/print_preview/destination_dialog_cros_interactive_test.js
index e5297b00..9e808e9f 100644
--- a/chrome/test/data/webui/print_preview/destination_dialog_cros_interactive_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dialog_cros_interactive_test.js
@@ -43,7 +43,7 @@
 
     // Create destinations.
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     setNativeLayerCrosInstance();
     const localDestinations = [];
     const destinations = getDestinations(localDestinations);
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_cros_test.js b/chrome/test/data/webui/print_preview/destination_dialog_cros_test.js
index 09df9e22..f3d49d8 100644
--- a/chrome/test/data/webui/print_preview/destination_dialog_cros_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dialog_cros_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeLayerImpl, PrintPreviewDestinationDialogCrosElement, PrintPreviewSearchBoxElement} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeLayerImpl, PrintPreviewDestinationDialogCrosElement, PrintPreviewSearchBoxElement} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
@@ -63,7 +63,7 @@
   setup(function() {
     // Create data classes
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     nativeLayerCros = setNativeLayerCrosInstance();
     cloudPrintInterface = new CloudPrintInterfaceStub();
     destinationStore = createDestinationStore();
@@ -284,7 +284,7 @@
         destinationStore.setActiveUser(user2);
         dialog.activeUser = user2;
         const whenInserted = eventToPromise(
-            DestinationStore.EventType.DESTINATIONS_INSERTED, destinationStore);
+            DestinationStoreEventType.DESTINATIONS_INSERTED, destinationStore);
         destinationStore.reloadUserCookieBasedDestinations(user2);
 
         await whenInserted;
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js
index 9f503572..137047a 100644
--- a/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dialog_interactive_test.js
@@ -42,7 +42,7 @@
 
     // Create destinations.
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     const localDestinations = [];
     const destinations = getDestinations(localDestinations);
     const recentDestinations = [makeRecentDestination(destinations[4])];
diff --git a/chrome/test/data/webui/print_preview/destination_dialog_test.js b/chrome/test/data/webui/print_preview/destination_dialog_test.js
index 62f6d34..2c8dce3 100644
--- a/chrome/test/data/webui/print_preview/destination_dialog_test.js
+++ b/chrome/test/data/webui/print_preview/destination_dialog_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeLayerImpl, PrintPreviewDestinationDialogElement} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeLayerImpl, PrintPreviewDestinationDialogElement} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {keyEventOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
@@ -56,7 +56,7 @@
   setup(function() {
     // Create data classes
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     cloudPrintInterface = new CloudPrintInterfaceStub();
     destinationStore = createDestinationStore();
     destinationStore.setCloudPrintInterface(cloudPrintInterface);
@@ -282,7 +282,7 @@
     destinationStore.setActiveUser(user2);
     dialog.activeUser = user2;
     const whenInserted = eventToPromise(
-        DestinationStore.EventType.DESTINATIONS_INSERTED, destinationStore);
+        DestinationStoreEventType.DESTINATIONS_INSERTED, destinationStore);
     destinationStore.reloadUserCookieBasedDestinations(user2);
 
     await whenInserted;
diff --git a/chrome/test/data/webui/print_preview/destination_search_test.js b/chrome/test/data/webui/print_preview/destination_search_test.js
index bb7d0fa..16afeab7 100644
--- a/chrome/test/data/webui/print_preview/destination_search_test.js
+++ b/chrome/test/data/webui/print_preview/destination_search_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, NativeLayer, NativeLayerImpl, PrintPreviewDestinationDialogElement} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, NativeLayer, NativeLayerImpl, PrintPreviewDestinationDialogElement} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -41,7 +41,7 @@
   setup(function() {
     // Create data classes
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     destinationStore = createDestinationStore();
     nativeLayer.setLocalDestinationCapabilities(
         getCddTemplate('FooDevice', 'FooName'));
@@ -104,7 +104,7 @@
         nativeLayer.setLocalDestinationCapabilities(getCddTemplate(destId));
 
         const waiter = eventToPromise(
-            DestinationStore.EventType.DESTINATION_SELECT,
+            DestinationStoreEventType.DESTINATION_SELECT,
             /** @type {!EventTarget} */ (destinationStore));
         requestSetup(destId);
         return Promise
diff --git a/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js b/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js
index a8fa306..ae73beb 100644
--- a/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js
+++ b/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, NativeLayerCrosImpl, NativeLayerImpl, PrintPreviewDestinationDialogCrosElement} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, NativeLayerCrosImpl, NativeLayerImpl, PrintPreviewDestinationDialogCrosElement} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -48,7 +48,7 @@
   setup(function() {
     // Create data classes
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     nativeLayerCros = new NativeLayerCrosStub();
     NativeLayerCrosImpl.setInstance(nativeLayerCros);
     destinationStore = createDestinationStore();
@@ -117,7 +117,7 @@
         nativeLayerCros.setSetupPrinterResponse(response);
 
         const waiter = eventToPromise(
-            DestinationStore.EventType.DESTINATION_SELECT,
+            DestinationStoreEventType.DESTINATION_SELECT,
             /** @type {!EventTarget} */ (destinationStore));
         requestSetup(destId);
         return Promise.all([nativeLayerCros.whenCalled('setupPrinter'), waiter])
diff --git a/chrome/test/data/webui/print_preview/destination_select_test_cros.js b/chrome/test/data/webui/print_preview/destination_select_test_cros.js
index 1e91352..5519aea 100644
--- a/chrome/test/data/webui/print_preview/destination_select_test_cros.js
+++ b/chrome/test/data/webui/print_preview/destination_select_test_cros.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, NativeLayer, NativeLayerCros, NativeLayerCrosImpl, NativeLayerImpl, PrinterStatus, PrinterStatusReason, PrinterStatusSeverity, PrintPreviewDestinationDropdownCrosElement, PrintPreviewDestinationSelectCrosElement, SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, NativeLayer, NativeLayerCros, NativeLayerCrosImpl, NativeLayerImpl, PrinterStatusReason, PrinterStatusSeverity, PrintPreviewDestinationDropdownCrosElement, PrintPreviewDestinationSelectCrosElement, SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {Base, flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -154,7 +154,7 @@
     document.body.innerHTML = '';
 
     // Stub out native layer.
-    NativeLayerImpl.instance_ = new NativeLayerStub();
+    NativeLayerImpl.setInstance(new NativeLayerStub());
     nativeLayerCros = new NativeLayerCrosStub();
     NativeLayerCrosImpl.setInstance(nativeLayerCros);
     setNativeLayerPrinterStatusMap();
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js
index d2a26164..de4dd0c 100644
--- a/chrome/test/data/webui/print_preview/destination_settings_test.js
+++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {CloudPrintInterface, CloudPrintInterfaceEventType, CloudPrintInterfaceImpl, Destination, DestinationConnectionStatus, DestinationErrorType, DestinationOrigin, DestinationState, DestinationStore, DestinationType, Error, GooglePromotedDestinationId, makeRecentDestination, NativeLayer, NativeLayerImpl, NUM_PERSISTED_DESTINATIONS, PrintPreviewDestinationSettingsElement, State} from 'chrome://print/print_preview.js';
+import {CloudPrintInterface, CloudPrintInterfaceEventType, CloudPrintInterfaceImpl, Destination, DestinationConnectionStatus, DestinationErrorType, DestinationOrigin, DestinationState, DestinationStore, DestinationStoreEventType, DestinationType, Error, GooglePromotedDestinationId, makeRecentDestination, NativeLayer, NativeLayerImpl, NUM_PERSISTED_DESTINATIONS, PrintPreviewDestinationSettingsElement, State} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {isChromeOS, isLacros, webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -86,7 +86,7 @@
 
     // Stub out native layer and cloud print interface.
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
@@ -139,7 +139,7 @@
         assertFalse(dropdown.loaded);
 
         return eventToPromise(
-                   DestinationStore.EventType
+                   DestinationStoreEventType
                        .SELECTED_DESTINATION_CAPABILITIES_READY,
                    destinationSettings.getDestinationStoreForTest())
             .then(() => {
@@ -165,7 +165,7 @@
               destinationSettings.disabled = false;
               destinationSettings.getDestinationStoreForTest().dispatchEvent(
                   new CustomEvent(
-                      DestinationStore.EventType.ERROR,
+                      DestinationStoreEventType.ERROR,
                       {detail: DestinationErrorType.INVALID}));
               flush();
 
@@ -179,7 +179,7 @@
               // Simulate the user having no printers.
               destinationSettings.getDestinationStoreForTest().dispatchEvent(
                   new CustomEvent(
-                      DestinationStore.EventType.ERROR,
+                      DestinationStoreEventType.ERROR,
                       {detail: DestinationErrorType.NO_DESTINATIONS}));
               flush();
 
@@ -429,7 +429,7 @@
             0, 1,
             makeRecentDestination(getGoogleDriveDestination(defaultUser)));
         const whenSelected = eventToPromise(
-            DestinationStore.EventType.DESTINATION_SELECT,
+            DestinationStoreEventType.DESTINATION_SELECT,
             destinationSettings.getDestinationStoreForTest());
         cloudPrintInterface.setPrinter(getGoogleDriveDestination(defaultUser));
         initialize();
@@ -509,7 +509,7 @@
 
           // Simulate selection of Save as PDF printer.
           const whenDestinationSelect = eventToPromise(
-              DestinationStore.EventType.DESTINATION_SELECT,
+              DestinationStoreEventType.DESTINATION_SELECT,
               destinationSettings.getDestinationStoreForTest());
           dropdown.fire('selected-option-change', 'Save as PDF/local/');
 
@@ -571,7 +571,7 @@
 
               // Simulate selection of Google Drive printer.
               const whenDestinationSelect = eventToPromise(
-                  DestinationStore.EventType.DESTINATION_SELECT,
+                  DestinationStoreEventType.DESTINATION_SELECT,
                   destinationSettings.getDestinationStoreForTest());
               dropdown.fire('selected-option-change', driveDestinationKey);
               return whenDestinationSelect;
@@ -621,7 +621,7 @@
 
               // Simulate selection of Save as PDF printer.
               const whenDestinationSelect = eventToPromise(
-                  DestinationStore.EventType.DESTINATION_SELECT,
+                  DestinationStoreEventType.DESTINATION_SELECT,
                   destinationSettings.getDestinationStoreForTest());
               dropdown.fire(
                   'selected-option-change', makeLocalDestinationKey('ID2'));
@@ -743,7 +743,7 @@
                       'print-preview-destination-dialog');
               assertTrue(dialog.isOpen());
               const whenAdded = eventToPromise(
-                  DestinationStore.EventType.DESTINATIONS_INSERTED,
+                  DestinationStoreEventType.DESTINATIONS_INSERTED,
                   destinationSettings.getDestinationStoreForTest());
               // Simulate setting a new account.
               dialog.fire('account-change', account2);
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test_cros.js b/chrome/test/data/webui/print_preview/destination_settings_test_cros.js
index 4c9d9d45..0aa8ae3 100644
--- a/chrome/test/data/webui/print_preview/destination_settings_test_cros.js
+++ b/chrome/test/data/webui/print_preview/destination_settings_test_cros.js
@@ -55,7 +55,7 @@
 
     // Stub out native layer.
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     nativeLayerCros = new NativeLayerCrosStub();
     NativeLayerCrosImpl.setInstance(nativeLayerCros);
 
diff --git a/chrome/test/data/webui/print_preview/destination_store_test.js b/chrome/test/data/webui/print_preview/destination_store_test.js
index 7847bb5..09ae381 100644
--- a/chrome/test/data/webui/print_preview/destination_store_test.js
+++ b/chrome/test/data/webui/print_preview/destination_store_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {CloudPrintInterfaceEventType, Destination, DestinationConnectionStatus, DestinationErrorType, DestinationOrigin, DestinationStore, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeInitialSettings, NativeLayerImpl, PrinterType} from 'chrome://print/print_preview.js';
+import {CloudPrintInterfaceEventType, Destination, DestinationConnectionStatus, DestinationErrorType, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, GooglePromotedDestinationId, makeRecentDestination, NativeInitialSettings, NativeLayerImpl, PrinterType} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {isChromeOS, isLacros} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
@@ -80,7 +80,7 @@
     setupTestListenerElement();
 
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
@@ -119,7 +119,7 @@
     }
 
     destinationStore.addEventListener(
-        DestinationStore.EventType.DESTINATION_SELECT, function() {
+        DestinationStoreEventType.DESTINATION_SELECT, function() {
           numPrintersSelected++;
         });
 
@@ -128,7 +128,7 @@
         JSON.parse(initialSettings.serializedAppStateStr).recentDestinations :
         [];
     const whenCapabilitiesReady = eventToPromise(
-        DestinationStore.EventType.SELECTED_DESTINATION_CAPABILITIES_READY,
+        DestinationStoreEventType.SELECTED_DESTINATION_CAPABILITIES_READY,
         destinationStore);
     destinationStore.init(
         initialSettings.pdfPrinterDisabled, !!initialSettings.isDriveMounted,
@@ -362,7 +362,7 @@
             .all([
               setInitialSettings(false),
               eventToPromise(
-                  DestinationStore.EventType
+                  DestinationStoreEventType
                       .SELECTED_DESTINATION_CAPABILITIES_READY,
                   destinationStore),
             ])
@@ -418,8 +418,7 @@
         return Promise
             .all([
               setInitialSettings(true),
-              eventToPromise(
-                  DestinationStore.EventType.ERROR, destinationStore),
+              eventToPromise(DestinationStoreEventType.ERROR, destinationStore),
             ])
             .then(function(argsArray) {
               const errorEvent = argsArray[1];
diff --git a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
index 08332db..21f4a215 100644
--- a/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
+++ b/chrome/test/data/webui/print_preview/invalid_settings_browsertest.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {CloudPrintInterfaceEventType, CloudPrintInterfaceImpl, Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationType, makeRecentDestination, MeasurementSystemUnitType, NativeInitialSettings, NativeLayer, NativeLayerImpl, PluginProxyImpl, PrintPreviewAppElement, PrintPreviewDestinationSettingsElement, PrintPreviewLayoutSettingsElement, PrintPreviewNumberSettingsSectionElement, PrintPreviewPreviewAreaElement, PrintPreviewSidebarElement, ScalingType, State, whenReady} from 'chrome://print/print_preview.js';
+import {CloudPrintInterfaceEventType, CloudPrintInterfaceImpl, Destination, DestinationConnectionStatus, DestinationOrigin, DestinationStore, DestinationStoreEventType, DestinationType, makeRecentDestination, MeasurementSystemUnitType, NativeInitialSettings, NativeLayer, NativeLayerImpl, PluginProxyImpl, PrintPreviewAppElement, PrintPreviewDestinationSettingsElement, PrintPreviewLayoutSettingsElement, PrintPreviewNumberSettingsSectionElement, PrintPreviewPreviewAreaElement, PrintPreviewSidebarElement, ScalingType, State, whenReady} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {isWindows} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
@@ -70,7 +70,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
@@ -462,7 +462,7 @@
 
               // Select the invalid destination and wait for the event.
               const whenInvalid = eventToPromise(
-                  DestinationStore.EventType.ERROR,
+                  DestinationStoreEventType.ERROR,
                   destinationSettings.getDestinationStoreForTest());
               destinationSettings.getDestinationStoreForTest()
                   .selectDestination(invalidPrinter);
@@ -478,7 +478,7 @@
 
               // Reselect the valid cloud destination.
               const whenSelected = eventToPromise(
-                  DestinationStore.EventType.DESTINATION_SELECT,
+                  DestinationStoreEventType.DESTINATION_SELECT,
                   destinationSettings.getDestinationStoreForTest());
               destinationSettings.getDestinationStoreForTest()
                   .selectDestination(validPrinter);
diff --git a/chrome/test/data/webui/print_preview/key_event_test.js b/chrome/test/data/webui/print_preview/key_event_test.js
index 9ec008c..09cb044 100644
--- a/chrome/test/data/webui/print_preview/key_event_test.js
+++ b/chrome/test/data/webui/print_preview/key_event_test.js
@@ -52,7 +52,7 @@
     nativeLayer.setLocalDestinationCapabilities(
         getCddTemplateWithAdvancedSettings(1, initialSettings.printerName));
     nativeLayer.setPageCount(3);
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/policy_test.js b/chrome/test/data/webui/print_preview/policy_test.js
index c9296d2..c45b476c 100644
--- a/chrome/test/data/webui/print_preview/policy_test.js
+++ b/chrome/test/data/webui/print_preview/policy_test.js
@@ -69,7 +69,7 @@
     nativeLayer.setLocalDestinations(
         [{deviceName: initialSettings.printerName, printerName: 'FooName'}]);
     nativeLayer.setPageCount(3);
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/preview_area_test.js b/chrome/test/data/webui/print_preview/preview_area_test.js
index b00d56c8..7f8dbb7 100644
--- a/chrome/test/data/webui/print_preview/preview_area_test.js
+++ b/chrome/test/data/webui/print_preview/preview_area_test.js
@@ -29,7 +29,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     nativeLayer.setPageCount(3);
     pluginProxy = new TestPluginProxy();
     PluginProxyImpl.instance_ = pluginProxy;
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.js b/chrome/test/data/webui/print_preview/preview_generation_test.js
index d37cc23..d96b4e828 100644
--- a/chrome/test/data/webui/print_preview/preview_generation_test.js
+++ b/chrome/test/data/webui/print_preview/preview_generation_test.js
@@ -60,7 +60,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/print_button_test.js b/chrome/test/data/webui/print_preview/print_button_test.js
index e79c0d1..eeab3dbe 100644
--- a/chrome/test/data/webui/print_preview/print_button_test.js
+++ b/chrome/test/data/webui/print_preview/print_button_test.js
@@ -40,7 +40,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/print_preview_app_test.js b/chrome/test/data/webui/print_preview/print_preview_app_test.js
index f5983de..7cc7dff 100644
--- a/chrome/test/data/webui/print_preview/print_preview_app_test.js
+++ b/chrome/test/data/webui/print_preview/print_preview_app_test.js
@@ -79,7 +79,7 @@
     // Stub out the native layer, the cloud print interface, and the plugin.
     document.body.innerHTML = '';
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/print_preview_sidebar_test.js b/chrome/test/data/webui/print_preview/print_preview_sidebar_test.js
index de2c1503..5c6d488 100644
--- a/chrome/test/data/webui/print_preview/print_preview_sidebar_test.js
+++ b/chrome/test/data/webui/print_preview/print_preview_sidebar_test.js
@@ -39,7 +39,7 @@
   setup(function() {
     // Stub out the native layer and cloud print interface
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/print_server_store_test.js b/chrome/test/data/webui/print_preview/print_server_store_test.js
index 295b0b7..0f9d1cb4 100644
--- a/chrome/test/data/webui/print_preview/print_server_store_test.js
+++ b/chrome/test/data/webui/print_preview/print_server_store_test.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {PrinterType, PrintServerStore} from 'chrome://print/print_preview.js';
+import {PrinterType, PrintServerStore, PrintServerStoreEventType} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {addWebUIListener, removeWebUIListener, WebUIListener, webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 
@@ -84,7 +84,7 @@
           {id: 'server2', name: 'Print Server 2'},
         ];
         const whenPrintServersChangedEvent = eventToPromise(
-            PrintServerStore.EventType.PRINT_SERVERS_CHANGED, printServerStore);
+            PrintServerStoreEventType.PRINT_SERVERS_CHANGED, printServerStore);
 
         const printServersConfig = {
           printServers: printServers,
@@ -133,7 +133,7 @@
       assert(print_server_store_test.TestNames.ServerPrintersLoading),
       async () => {
         const whenServerPrintersLoadedEvent = eventToPromise(
-            PrintServerStore.EventType.SERVER_PRINTERS_LOADING,
+            PrintServerStoreEventType.SERVER_PRINTERS_LOADING,
             printServerStore);
 
         webUIListenerCallback('server-printers-loading', true);
diff --git a/chrome/test/data/webui/print_preview/restore_state_test.js b/chrome/test/data/webui/print_preview/restore_state_test.js
index 7c7e33f9..b522df9 100644
--- a/chrome/test/data/webui/print_preview/restore_state_test.js
+++ b/chrome/test/data/webui/print_preview/restore_state_test.js
@@ -31,7 +31,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
index 1902aae..ddfa1831 100644
--- a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
+++ b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
@@ -37,7 +37,7 @@
   /** @override */
   setup(function() {
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     document.body.innerHTML = '';
 
     const initialSettings = getDefaultInitialSettings();
diff --git a/chrome/test/data/webui/print_preview/user_manager_test.js b/chrome/test/data/webui/print_preview/user_manager_test.js
index 4e386b54..ad57828 100644
--- a/chrome/test/data/webui/print_preview/user_manager_test.js
+++ b/chrome/test/data/webui/print_preview/user_manager_test.js
@@ -41,7 +41,7 @@
 
     // Create data classes
     nativeLayer = new NativeLayerStub();
-    NativeLayerImpl.instance_ = nativeLayer;
+    NativeLayerImpl.setInstance(nativeLayer);
     // <if expr="chromeos or lacros">
     setNativeLayerCrosInstance();
     // </if>
diff --git a/chrome/test/data/webui/settings/BUILD.gn b/chrome/test/data/webui/settings/BUILD.gn
index afe5271..ad29a54 100644
--- a/chrome/test/data/webui/settings/BUILD.gn
+++ b/chrome/test/data/webui/settings/BUILD.gn
@@ -139,7 +139,6 @@
     #":test_extension_control_browser_proxy",
     ":test_hats_browser_proxy",
     ":test_lifetime_browser_proxy",
-    ":test_local_data_browser_proxy",
     ":test_metrics_browser_proxy",
     ":test_open_window_proxy",
 
@@ -149,7 +148,6 @@
     #":test_reset_browser_proxy",
     #":test_search_engines_browser_proxy",
     ":test_sync_browser_proxy",
-    ":test_util",
 
     #":zoom_levels_tests",
   ]
@@ -302,13 +300,6 @@
   ]
 }
 
-js_library("test_local_data_browser_proxy") {
-  deps = [
-    "..:test_browser_proxy",
-    "//chrome/browser/resources/settings:lazy_load",
-  ]
-}
-
 js_library("test_search_engines_browser_proxy") {
   deps = [
     "..:test_browser_proxy",
@@ -322,10 +313,3 @@
     "//chrome/browser/resources/settings:settings",
   ]
 }
-
-js_library("test_util") {
-  deps = [
-    "//chrome/browser/resources/settings:lazy_load",
-    "//chrome/browser/resources/settings:settings",
-  ]
-}
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index 7325639..2377c2d 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -144,6 +144,7 @@
     "os_settings_menu_test.js",
     "os_settings_ui_test.js",
     "os_settings_ui_test_2.js",
+    "os_sync_controls_optional_disabled_test.js",
     "os_sync_controls_test.js",
     "parental_controls_page_test.js",
     "people_page_account_manager_test.js",
diff --git a/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
index 1f28277..c9c106c 100644
--- a/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/app_notifications_subpage_tests.js
@@ -331,17 +331,17 @@
     assertEquals('App2', appRow1.$.appTitle.textContent.trim());
   });
 
-  // TODO(crbug/1240175): Ensure that CrToggle is disabled correctly and
-  // CrPolicyIndicator is hidden correctly.
   test('Each app-notification-row displays correctly', async () => {
+    const appTitle1 = 'Files';
+    const appTitle2 = 'Chrome';
     const permission1 = createPermission(
         /**id=*/ 1, /**value_type=*/ 0,
         /**value=*/ 0, /**is_managed=*/ true);
     const permission2 = createPermission(
         /**id=*/ 2, /**value_type=*/ 0,
         /**value=*/ 1, /**is_managed=*/ false);
-    const app1 = createApp('1', 'Chrome', permission1);
-    const app2 = createApp('2', 'Files', permission2);
+    const app1 = createApp('file-id', appTitle1, permission1);
+    const app2 = createApp('chrome-id', appTitle2, permission2);
 
     await initializeObserver;
     simulateNotificationAppChanged(app1);
@@ -354,13 +354,19 @@
     assertTrue(!!page);
     flush();
 
-    assertEquals('Chrome', chromeRow.$.appTitle.textContent.trim());
-    assertTrue(chromeRow.$.appToggle.disabled);
-    assertTrue(!!chromeRow.shadowRoot.querySelector('cr-policy-indicator'));
+    // Apps should be listed in alphabetical order. |appTitle1| should come
+    // before |appTitle2|, so a 1 should be returned by localCompare.
+    const expected = 1;
+    const actual = appTitle1.localeCompare(appTitle2);
+    assertEquals(expected, actual);
 
-    assertEquals('Files', filesRow.$.appTitle.textContent.trim());
-    assertFalse(filesRow.$.appToggle.disabled);
-    assertFalse(!!filesRow.shadowRoot.querySelector('cr-policy-indicator'));
+    assertEquals(appTitle2, chromeRow.$.appTitle.textContent.trim());
+    assertFalse(chromeRow.$.appToggle.disabled);
+    assertFalse(!!chromeRow.shadowRoot.querySelector('cr-policy-indicator'));
+
+    assertEquals(appTitle1, filesRow.$.appTitle.textContent.trim());
+    assertTrue(filesRow.$.appToggle.disabled);
+    assertTrue(!!filesRow.shadowRoot.querySelector('cr-policy-indicator'));
   });
 
   test('toggleDoNotDisturb', function() {
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 09c32ad5..c665238 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -217,8 +217,7 @@
   get featureList() {
     return {
       enabled: super.featureList.enabled.concat([
-        // TODO(https://crbug.com/1227693): Remove kSplitSettingsSync.
-        'chromeos::features::kSplitSettingsSync',
+        'chromeos::features::kSyncConsentOptional',
         'chromeos::features::kSyncSettingsCategorization'
       ])
     };
@@ -230,6 +229,30 @@
 });
 
 // eslint-disable-next-line no-var
+var OSSettingsPeoplePageOsSyncOptionalDisabledV3Test =
+    class extends OSSettingsV3BrowserTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://os-settings/test_loader.html?module=settings/chromeos/' +
+      'os_sync_controls_optional_disabled_test.m.js';
+  }
+
+  /** @override */
+  get featureList() {
+    return {
+      enabled: super.featureList.enabled.concat(
+          ['chromeos::features::kSyncSettingsCategorization']),
+      disabled: ['chromeos::features::kSyncConsentOptional']
+    };
+  }
+};
+
+TEST_F('OSSettingsPeoplePageOsSyncOptionalDisabledV3Test', 'AllJsTests', () => {
+  mocha.run();
+});
+
+
+// eslint-disable-next-line no-var
 var OSSettingsPeoplePageV3Test = class extends OSSettingsV3BrowserTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/settings/chromeos/os_sync_controls_optional_disabled_test.js b/chrome/test/data/webui/settings/chromeos/os_sync_controls_optional_disabled_test.js
new file mode 100644
index 0000000..e9b48cd
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/os_sync_controls_optional_disabled_test.js
@@ -0,0 +1,268 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {OsSyncBrowserProxyImpl, Router, StatusAction, routes} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {flush} from'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {waitAfterNextRender} from 'chrome://test/test_util.js';
+// #import {getDeepActiveElement} from 'chrome://resources/js/util.m.js';
+// #import {TestBrowserProxy} from '../../test_browser_proxy.js';
+// clang-format on
+
+/** @implements {settings.OsSyncBrowserProxy} */
+class TestOsSyncBrowserProxy extends TestBrowserProxy {
+  constructor() {
+    super([
+      'didNavigateToOsSyncPage',
+      'didNavigateAwayFromOsSyncPage',
+      'setOsSyncFeatureEnabled',
+      'setOsSyncDatatypes',
+    ]);
+  }
+
+  /** @override */
+  didNavigateToOsSyncPage() {
+    this.methodCalled('didNavigateToOsSyncPage');
+  }
+
+  /** @override */
+  didNavigateAwayFromOsSyncPage() {
+    this.methodCalled('didNavigateAwayFromSyncPage');
+  }
+
+  /** @override */
+  setOsSyncFeatureEnabled(enabled) {
+    this.methodCalled('setOsSyncFeatureEnabled', enabled);
+  }
+
+  /** @override */
+  setOsSyncDatatypes(osSyncPrefs) {
+    this.methodCalled('setOsSyncDatatypes', osSyncPrefs);
+  }
+}
+
+/**
+ * Returns a sync prefs dictionary with either all or nothing syncing.
+ * @param {boolean} syncAll
+ * @return {!settings.OsSyncPrefs}
+ */
+function getOsSyncPrefs(syncAll) {
+  return {
+    osAppsRegistered: true,
+    osAppsSynced: syncAll,
+    osPreferencesRegistered: true,
+    osPreferencesSynced: syncAll,
+    syncAllOsTypes: syncAll,
+    wallpaperEnabled: syncAll,
+    wifiConfigurationsRegistered: true,
+    wifiConfigurationsSynced: syncAll,
+  };
+}
+
+function getSyncAllPrefs() {
+  return getOsSyncPrefs(true);
+}
+
+function getSyncNothingPrefs() {
+  return getOsSyncPrefs(false);
+}
+
+// Returns a SyncStatus representing the default syncing state.
+function getDefaultSyncStatus() {
+  return {
+    disabled: false,
+    hasError: false,
+    hasUnrecoverableError: false,
+    signedIn: true,
+    statusAction: settings.StatusAction.NO_ACTION,
+  };
+}
+
+function setupWithFeatureEnabled() {
+  cr.webUIListenerCallback(
+      'os-sync-prefs-changed', /*featureEnabled=*/ true, getSyncAllPrefs());
+  Polymer.dom.flush();
+}
+
+suite('OsSyncControlsTest', function() {
+  let browserProxy = null;
+  let syncControls = null;
+  let syncIconContainer = null;
+
+  setup(function() {
+    browserProxy = new TestOsSyncBrowserProxy();
+    settings.OsSyncBrowserProxyImpl.instance_ = browserProxy;
+
+    PolymerTest.clearBody();
+    syncControls = document.createElement('os-sync-controls');
+    syncControls.syncStatus = getDefaultSyncStatus();
+    syncControls.profileName = 'John Cena';
+    syncControls.profileEmail = 'john.cena@gmail.com';
+    syncControls.profileIconUrl = 'data:image/png;base64,abc123';
+    document.body.appendChild(syncControls);
+
+    // Alias to help with line wrapping in test cases.
+    syncIconContainer = syncControls.$.syncIconContainer;
+  });
+
+  teardown(function() {
+    syncControls.remove();
+    settings.Router.getInstance().resetRouteForTesting();
+  });
+
+  test('ControlsHiddenUntilInitialUpdateSent', function() {
+    assertTrue(syncControls.hidden);
+    setupWithFeatureEnabled();
+    assertFalse(syncControls.hidden);
+  });
+
+  test('Avatar icon', function() {
+    assertEquals('data:image/png;base64,abc123', syncControls.$.avatarIcon.src);
+  });
+
+  test('Status icon is visible with feature enabled', function() {
+    setupWithFeatureEnabled();
+    assertFalse(syncControls.$.syncIconContainer.hidden);
+  });
+
+  test('Status icon with error', function() {
+    setupWithFeatureEnabled();
+    const status = getDefaultSyncStatus();
+    status.hasError = true;
+    syncControls.syncStatus = status;
+
+    assertTrue(syncIconContainer.classList.contains('sync-problem'));
+    assertTrue(!!syncControls.$$('[icon="settings:sync-problem"]'));
+  });
+
+  test('Status icon with sync paused for reauthentication', function() {
+    setupWithFeatureEnabled();
+    const status = getDefaultSyncStatus();
+    status.hasError = true;
+    status.statusAction = settings.StatusAction.REAUTHENTICATE;
+    syncControls.syncStatus = status;
+
+    assertTrue(syncIconContainer.classList.contains('sync-paused'));
+    assertTrue(!!syncControls.$$('[icon="settings:sync-disabled"]'));
+  });
+
+  test('Status icon with sync disabled', function() {
+    setupWithFeatureEnabled();
+    const status = getDefaultSyncStatus();
+    status.disabled = true;
+    syncControls.syncStatus = status;
+
+    assertTrue(syncIconContainer.classList.contains('sync-disabled'));
+    assertTrue(!!syncControls.$$('[icon="cr:sync"]'));
+  });
+
+  test('Account name and email with feature enabled', function() {
+    setupWithFeatureEnabled();
+    assertEquals('John Cena', syncControls.$.accountTitle.textContent.trim());
+    assertEquals(
+        'Syncing to john.cena@gmail.com',
+        syncControls.$.accountSubtitle.textContent.trim());
+  });
+
+  test('Account name and email with sync error', function() {
+    setupWithFeatureEnabled();
+    syncControls.syncStatus = {hasError: true};
+    Polymer.dom.flush();
+    assertEquals(
+        `Sync isn't working`, syncControls.$.accountTitle.textContent.trim());
+    assertEquals(
+        'john.cena@gmail.com',
+        syncControls.$.accountSubtitle.textContent.trim());
+  });
+
+  // Regression test for https://crbug.com/1076239
+  test('Handles undefined syncStatus', function() {
+    syncControls.syncStatus = undefined;
+    setupWithFeatureEnabled();
+    assertEquals('', syncControls.$.accountTitle.textContent.trim());
+    assertEquals('', syncControls.$.accountSubtitle.textContent.trim());
+  });
+
+  test('FeatureEnabled', function() {
+    setupWithFeatureEnabled();
+
+    // the button is always hidden when kSyncConsentOptional is disabled.
+    assertTrue(!syncControls.$$('#syncOnOffButton'));
+
+    assertFalse(syncControls.$.syncEverythingCheckboxLabel.hasAttribute(
+        'label-disabled'));
+
+    const syncAllControl = syncControls.$.syncAllOsTypesControl;
+    assertFalse(syncAllControl.disabled);
+    assertTrue(syncAllControl.checked);
+
+    const labels = syncControls.shadowRoot.querySelectorAll(
+        '.list-item:not([hidden]) > div.checkbox-label');
+    for (const label of labels) {
+      assertFalse(label.hasAttribute('label-disabled'));
+    }
+
+    const datatypeControls = syncControls.shadowRoot.querySelectorAll(
+        '.list-item:not([hidden]) > cr-toggle');
+    for (const control of datatypeControls) {
+      assertTrue(control.disabled);
+      assertTrue(control.checked);
+    }
+  });
+
+  test('UncheckingSyncAllEnablesAllIndividualControls', async function() {
+    setupWithFeatureEnabled();
+    syncControls.$.syncAllOsTypesControl.click();
+    const prefs = await browserProxy.whenCalled('setOsSyncDatatypes');
+
+    const expectedPrefs = getSyncAllPrefs();
+    expectedPrefs.syncAllOsTypes = false;
+    assertEquals(JSON.stringify(expectedPrefs), JSON.stringify(prefs));
+  });
+
+  test('PrefChangeUpdatesControls', function() {
+    const prefs = getSyncAllPrefs();
+    prefs.syncAllOsTypes = false;
+    cr.webUIListenerCallback(
+        'os-sync-prefs-changed', /*featureEnabled=*/ true, prefs);
+
+    const datatypeControls = syncControls.shadowRoot.querySelectorAll(
+        '.list-item:not([hidden]) > cr-toggle');
+    for (const control of datatypeControls) {
+      assertFalse(control.disabled);
+      assertTrue(control.checked);
+    }
+  });
+
+  test('DisablingOneControlUpdatesPrefs', async function() {
+    setupWithFeatureEnabled();
+
+    // Disable "Sync All".
+    syncControls.$.syncAllOsTypesControl.click();
+    // Disable "Settings".
+    syncControls.$.osPreferencesControl.click();
+    const prefs = await browserProxy.whenCalled('setOsSyncDatatypes');
+
+    const expectedPrefs = getSyncAllPrefs();
+    expectedPrefs.syncAllOsTypes = false;
+    expectedPrefs.osPreferencesSynced = false;
+    assertEquals(JSON.stringify(expectedPrefs), JSON.stringify(prefs));
+  });
+});
+
+suite('OsSyncControlsNavigationTest', function() {
+  test('DidNavigateEvents', async function() {
+    const browserProxy = new TestOsSyncBrowserProxy();
+    settings.OsSyncBrowserProxyImpl.instance_ = browserProxy;
+
+    settings.Router.getInstance().navigateTo(settings.routes.OS_SYNC);
+    await browserProxy.methodCalled('didNavigateToOsSyncPage');
+
+    settings.Router.getInstance().navigateTo(settings.routes.OS_PEOPLE);
+    await browserProxy.methodCalled('didNavigateAwayFromOsSyncPage');
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js b/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
index 3372145..2afb029 100644
--- a/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
+++ b/chrome/test/data/webui/settings/chromeos/os_sync_controls_test.js
@@ -210,7 +210,7 @@
   test('FeatureDisabled', function() {
     setupWithFeatureDisabled();
 
-    assertTrue(!!syncControls.$.syncOnOffButton);
+    assertTrue(!!syncControls.$$('#syncOnOffButton'));
 
     assertTrue(syncControls.$.syncEverythingCheckboxLabel.hasAttribute(
         'label-disabled'));
@@ -236,7 +236,7 @@
   test('FeatureEnabled', function() {
     setupWithFeatureEnabled();
 
-    assertTrue(!!syncControls.$.syncOnOffButton);
+    assertTrue(!!syncControls.$$('#syncOnOffButton'));
 
     assertFalse(syncControls.$.syncEverythingCheckboxLabel.hasAttribute(
         'label-disabled'));
@@ -261,7 +261,7 @@
 
   test('ClickingTurnOffDisablesFeature', async function() {
     setupWithFeatureEnabled();
-    syncControls.$.syncOnOffButton.click();
+    syncControls.$$('#syncOnOffButton').click();
     const enabled = await browserProxy.whenCalled('setOsSyncFeatureEnabled');
     assertFalse(enabled);
   });
@@ -273,7 +273,7 @@
     params.append('settingId', '302');
     settings.Router.getInstance().navigateTo(settings.routes.OS_SYNC, params);
 
-    const deepLinkElement = syncControls.$.syncOnOffButton;
+    const deepLinkElement = syncControls.$$('#syncOnOffButton');
     await test_util.waitAfterNextRender(deepLinkElement);
     assertEquals(
         deepLinkElement, getDeepActiveElement(),
@@ -282,7 +282,7 @@
 
   test('ClickingTurnOnEnablesFeature', async function() {
     setupWithFeatureDisabled();
-    syncControls.$.syncOnOffButton.click();
+    syncControls.$$('#syncOnOffButton').click();
     const enabled = await browserProxy.whenCalled('setOsSyncFeatureEnabled');
     assertTrue(enabled);
   });
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js
index 9df7bf95..86b622e 100644
--- a/chrome/test/data/webui/settings/site_list_tests.js
+++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -8,7 +8,7 @@
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-import {AddSiteDialogElement, ContentSetting, ContentSettingsTypes, SettingsEditExceptionDialogElement, SITE_EXCEPTION_WILDCARD, SiteException, SiteListElement, SiteSettingSource, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
+import {AddSiteDialogElement, ContentSetting, ContentSettingsTypes, SettingsEditExceptionDialogElement, SITE_EXCEPTION_WILDCARD, SiteListElement, SiteSettingSource, SiteSettingsPrefsBrowserProxyImpl} from 'chrome://settings/lazy_load.js';
 import {CrSettingsPrefs,Router} from 'chrome://settings/settings.js';
 
 import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../chai_assert.js';
diff --git a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
index 50b5bb2..421b164 100644
--- a/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
+++ b/chrome/test/data/webui/settings/test_local_data_browser_proxy.js
@@ -3,8 +3,6 @@
 // found in the LICENSE file.
 
 // clang-format off
-import {CookieDetails, LocalDataBrowserProxy, LocalDataItem} from 'chrome://settings/lazy_load.js';
-
 import {TestBrowserProxy} from '../test_browser_proxy.js';
 // clang-format on
 
diff --git a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
index 52f3903d..084df4a 100644
--- a/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
+++ b/chrome/test/data/webui/settings/test_site_settings_prefs_browser_proxy.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
-import {ContentSetting, ContentSettingsTypes, RawChooserException, RawSiteException, RecentSitePermissions, SiteSettingSource, SiteSettingsPrefsBrowserProxy, ZoomLevelEntry} from 'chrome://settings/lazy_load.js';
+import {ContentSetting, ContentSettingsTypes, SiteSettingSource} from 'chrome://settings/lazy_load.js';
 
 import {TestBrowserProxy} from '../test_browser_proxy.js';
 
diff --git a/chrome/test/data/webui/settings/test_util.js b/chrome/test/data/webui/settings/test_util.js
index 0fbca30d..c948968 100644
--- a/chrome/test/data/webui/settings/test_util.js
+++ b/chrome/test/data/webui/settings/test_util.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 // clang-format off
-import {ChooserType, ContentSetting, ContentSettingsTypes, DefaultContentSetting, RawChooserException, RawSiteException, SiteGroup, SiteSettingSource} from 'chrome://settings/lazy_load.js';
+import {ChooserType, ContentSetting, ContentSettingsTypes, SiteSettingSource} from 'chrome://settings/lazy_load.js';
 import {Route, Router} from 'chrome://settings/settings.js';
 // clang-format on
 
diff --git a/chrome/tools/build/mac/FILES.cfg b/chrome/tools/build/mac/FILES.cfg
index 7fbac1a..56ae287 100644
--- a/chrome/tools/build/mac/FILES.cfg
+++ b/chrome/tools/build/mac/FILES.cfg
@@ -140,19 +140,18 @@
   # Updater files:
   {
     'filename': 'GoogleUpdater.app',
-    'buildtype': ['official'],
+    'buildtype': ['dev', 'official'],
     'archive': 'updater.zip',
   },
   {
     'filename': 'chrome/updater/.install',
-    'buildtype': ['official'],
+    'buildtype': ['dev', 'official'],
     'archive': 'updater.zip',
   },
   {
     'filename': 'Updater Packaging',
-    'buildtype': ['official'],
+    'buildtype': ['dev', 'official'],
     'archive': 'updater.zip',
-    'optional': ['official'], # TODO(crbug.com/1024318): Make non-optional.
   },
   # Enterprise policy templates:
   {
diff --git a/chrome/tools/build/win/FILES.cfg b/chrome/tools/build/win/FILES.cfg
index b2e3a6e..2159093 100644
--- a/chrome/tools/build/win/FILES.cfg
+++ b/chrome/tools/build/win/FILES.cfg
@@ -731,24 +731,17 @@
     'buildtype': ['dev', 'official'],
     'archive': 'chrome-win32-syms.zip',
   },
-  # Updater files (official build only):
+  # Updater files:
   {
     'filename': 'updater.exe',
-    'buildtype': ['official'],
-    'optional': ['official'], # TODO(crbug.com/926234): Remove optional.
+    'buildtype': ['dev', 'official'],
     'archive': 'updater.zip',
   },
   {
     'filename': 'UpdaterSigning',
-    'buildtype': ['official'],
-    'optional': ['official'], # TODO(crbug.com/926234): Remove optional.
+    'buildtype': ['dev', 'official'],
     'archive': 'updater.zip',
   },
-  { # TODO(crbug.com/926234): Remove this upload after server side is updated.
-    'filename': 'updater.exe',
-    'buildtype': ['official'],
-    'archive': 'updater.exe',
-  },
   # Partner API files.
   {
     'filename': 'gcapi.h',
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index fd19aa5..982fa15 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -589,7 +589,9 @@
         "test/service/win/answer_uac.py",
         "test/service/win/impersonate.py",
         "test/service/win/proc_util.py",
+        "test/service/win/rpc_client.py",
         "test/service/win/rpc_handler.py",
+        "test/service/win/run_command_as_standard_user.py",
         "test/service/win/uac.py",
         "test/service/win/ui.py",
         "test/service/win/updater_test_service.py",
diff --git a/chrome/updater/mac/update_service_proxy_test.mm b/chrome/updater/mac/update_service_proxy_test.mm
index ee562ece..8bcbf7f 100644
--- a/chrome/updater/mac/update_service_proxy_test.mm
+++ b/chrome/updater/mac/update_service_proxy_test.mm
@@ -444,8 +444,8 @@
 }
 
 #pragma mark Test cases
-
-TEST_F(MacUpdateServiceProxyTest, NoProductsUpdateAll) {
+// TODO(crbug.com/1247504): Flaky on macOS 10.12.6.
+TEST_F(MacUpdateServiceProxyTest, DISABLED_NoProductsUpdateAll) {
   ScopedXPCServiceMock::ConnectionMockRecord* conn_rec =
       mock_driver_.PrepareNewMockConnection();
   ScopedXPCServiceMock::RemoteObjectMockRecord* mock_rec =
diff --git a/chrome/updater/test/service/win/impersonate.py b/chrome/updater/test/service/win/impersonate.py
index 2347c7a..116b555 100644
--- a/chrome/updater/test/service/win/impersonate.py
+++ b/chrome/updater/test/service/win/impersonate.py
@@ -20,6 +20,7 @@
 import win32ts
 import winerror
 
+import proc_util
 
 class ImpersonationError(Exception):
   """Error representing impersonation error."""
@@ -87,7 +88,7 @@
     win32file.CloseHandle(self.stderr_w)
 
 
-def _RunAsOnWindowStationDesktop(command,
+def _RunAsOnWindowStationDesktop(command_line,
                                  security_token,
                                  window_station,
                                  desktop,
@@ -97,7 +98,7 @@
   """Runs a command as the security token user on given desktop.
 
   Args:
-    command: Full command line string to run.
+    command_line: Full command line string to run.
     security_token: Security token that the command run as.
     window_station: Window station for the new process to run, tpically is
        "WinSta0", aka the interactive window station.
@@ -132,22 +133,22 @@
   env_block = win32profile.CreateEnvironmentBlock(security_token, True)
   (process_handle, unused_thread, pid,
    unused_thread_id) = win32process.CreateProcessAsUser(
-       security_token, None, command, None, None, 1,
+       security_token, None, command_line, None, None, 1,
        create_flags, env_block, cwd, si)
   if env:
     os.environ.clear()
     os.environ.update(saved_env)
   pipes.CloseWriteHandles()
   if not process_handle:
-    logging.error('Failed to create child process [%s] on [%s\\%s]', command,
-                  window_station, desktop)
+    logging.error('Failed to create child process [%s] on [%s\\%s]',
+                  command_line, window_station, desktop)
     raise ImpersonationError(
         'Failed to create process [%s] with impersonation: [%s\\%s][%s]' %
-        (command, window_station, desktop, cwd))
+        (command_line, window_station, desktop, cwd))
 
   pipes.ReadAll()
   logging.info('Child process [%s] created on [%s\\%s]',
-      command, window_station, desktop)
+      command_line, window_station, desktop)
   logging.info('Waiting %s seconds for child process.', timeout)
   if timeout != win32event.INFINITE:
     timeout *= 1000  # Convert from seconds to milli-seconds.
@@ -165,11 +166,11 @@
     return (pid, None, None, None)
 
 
-def RunAsConsoleUser(command, env, cwd, timeout):
-  """Runs a command as console user.
+def RunAsStandardUser(command_line, env, cwd, timeout):
+  """Runs a command as non-elevated logged-on user.
 
   Args:
-    command: The command line string, including arguments, to run.
+    command_line: The command line string, including arguments, to run.
     env: Environment variables for child process, None to inherit.
     cwd: Working directory for child process, None to inherit from parent.
     timeout: How long in seconds should wait for child process.
@@ -180,7 +181,7 @@
   Raises:
     ImpersonationError: when impersonation failed.
   """
-  logging.info('Running the command "%s" as the console user.', command)
+  logging.info('Running "%s" as the logon user.', command_line)
 
   # Adjust current process to be part of the trusted computer base.
   current_process_token = win32security.OpenProcessToken(
@@ -191,12 +192,12 @@
   win32security.AdjustTokenPrivileges(current_process_token, 0,
                                       [(tcb_privilege_flag, se_enable)])
 
-  console_session_id = ctypes.windll.kernel32.WTSGetActiveConsoleSessionId()
-  if not console_session_id:
-    raise ImpersonationError('Cannot find active console session.')
+  active_session_id = proc_util.GetActiveSessionID()
+  if not active_session_id:
+    raise ImpersonationError('Cannot find active logon session.')
 
   try:
-    console_user_token = win32ts.WTSQueryUserToken(console_session_id)
+    logon_user_token = win32ts.WTSQueryUserToken(active_session_id)
   except pywintypes.error as err:
     if err.winerror == winerror.ERROR_NO_TOKEN:
       raise ImpersonationError('No user is logged on.')
@@ -204,10 +205,10 @@
       raise ImpersonationError('Failed to get user token: %s' % err)
 
   return _RunAsOnWindowStationDesktop(
-      command, console_user_token, 'WinSta0', 'default', env, cwd, timeout)
+      command_line, logon_user_token, 'WinSta0', 'default', env, cwd, timeout)
 
 
-def RunAsPidOnDeskstop(command,
+def RunAsPidOnDeskstop(command_line,
                        pid,
                        window_station='WinSta0',
                        desktop='default',
@@ -217,7 +218,7 @@
   """Runs a command with pid's security token and on the given desktop.
 
   Args:
-    command: The command line string to run.
+    command_line: The command line string, including arguments, to run.
     pid: ID of the process to get the security token from.
     window_station: Window station for the new process to run, tpically is
        "WinSta0", aka the interactive window station.
@@ -234,7 +235,7 @@
     (pid, exit_code, stdout, stderr) tuple.
   """
 
-  logging.info('RunAsPidOnDeskstop: [%s][%s]', pid, command)
+  logging.info('RunAsPidOnDeskstop: [%s][%s]', pid, command_line)
 
   process_handle = None
   token_handle = None
@@ -243,7 +244,7 @@
     token_handle = win32security.OpenProcessToken(process_handle,
                                                   win32con.TOKEN_ALL_ACCESS)
     return _RunAsOnWindowStationDesktop(
-        command, token_handle, window_station, desktop, env, cwd, timeout)
+        command_line, token_handle, window_station, desktop, env, cwd, timeout)
   except (pywintypes.error, ImpersonationError) as err:
     logging.error(err)
     return (None, None, None, None)
diff --git a/chrome/updater/test/service/win/rpc_client.py b/chrome/updater/test/service/win/rpc_client.py
new file mode 100644
index 0000000..9588853
--- /dev/null
+++ b/chrome/updater/test/service/win/rpc_client.py
@@ -0,0 +1,106 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import logging
+import os
+import socket
+import sys
+import xmlrpclib
+
+
+# TODO(crbug.com/1233612): Query XML RPC server port once the server propgate
+# the value.
+_UPDATER_XML_RPC_PORT = 9090
+
+
+# Errors that might be raised when interacting with the RPC server.
+RPCErrors = (socket.error, socket.herror, socket.gaierror, socket.timeout)
+
+
+def GetProxy():
+  """Constructs a XML RPC server proxy."""
+  return xmlrpclib.ServerProxy(
+      'http://localhost:%s' % _UPDATER_XML_RPC_PORT)
+
+
+def TestConnection():
+  """Test that connection to the XML RPC server."""
+  try:
+    proxy = GetProxy()
+    return 'hi' == proxy.echo('hi')
+  except RPCErrors as err:
+    logging.error('Unable connect to XML RPC server')
+    logging.exception(err)
+    return False
+
+
+def RunAsSystem(command, env=None, cwd=None, timeout=90):
+  """Runs the command as SYSTEM user.
+
+  Args:
+    command: The command to run. This argument will be forwarded to
+      subprocess.Popen().
+    env: Environment variables to pass to command.
+    cwd: Working directory for the command.
+    timeout: How long the child process should wait for UAC before timeout.
+
+  Returns:
+    (pid, exit_code, sdtout, stderr) tuple.
+  """
+  try:
+    proxy = GetProxy()
+    env = env or dict(os.environ)
+    cwd = cwd or os.getcwd()
+    return proxy.RunAsSystem(command, env, cwd, timeout)
+  except RPCErrors as err:
+    logging.exception(err)
+    raise
+
+
+def RunAsStandardUser(command_line, env=None, cwd=None, timeout=90):
+  """Runs the command as the non-elevated logged-on user on default desktop.
+
+  Args:
+    command_line: The command line string, includes all arguments.
+    env: Environment variables to pass to command.
+    cwd: Working directory for the command.
+    timeout: How long the child process should wait before timeout.
+
+  Returns:
+    (pid, exit_code, sdtout, stderr) tuple.
+  """
+  try:
+    proxy = GetProxy()
+    env = env or dict(os.environ)
+    cwd = cwd or os.getcwd()
+    return proxy.RunAsStandardUser(command_line, env, cwd, timeout)
+  except RPCErrors as err:
+    logging.exception(err)
+    raise
+
+
+def AnswerUpcomingUACPrompt(actions,
+                            timeout=10,
+                            wait_child=False,
+                            source=''):
+  """Answers upcoming UAC prompt that does not require username/password.
+
+  Args:
+    actions: Actions to take in string, such as 'AADDA', 'A' to accept,
+        'D' to deny.
+    timeout: How long the child process should wait for each UAC click.
+    wait_child: Whether this thread should wait the completion of child proc.
+    source: Optional name of the source that triggers this action (for logging
+        and debugging purpose).
+
+  Returns:
+    (pid, exit_code) of the created UAC-answering process. If the sub-process
+    is not created, or did not finish in wait time, returns (None, None).
+  """
+  try:
+    proxy = GetProxy()
+    return proxy.AnswerUpcomingUACPrompt(actions, timeout, wait_child, source)
+  except RPCErrors as err:
+    logging.exception(err)
+    raise
diff --git a/chrome/updater/test/service/win/rpc_handler.py b/chrome/updater/test/service/win/rpc_handler.py
index 7f0be54..b4688cf2 100644
--- a/chrome/updater/test/service/win/rpc_handler.py
+++ b/chrome/updater/test/service/win/rpc_handler.py
@@ -21,10 +21,11 @@
     """Runs the command as SYSTEM user.
 
     Args:
-      command: The command to run.
+      command: The command to run. This argument will be forwarded to
+        subprocess.Popen().
       env: Environment variables to pass to command.
       cwd: Working directory for the command.
-      timeout: How long the child process should wait for UAC before timeout.
+      timeout: How long the child process should wait before timeout.
 
     Returns:
       (pid, exit_code, sdtout, stderr) tuple.
@@ -47,19 +48,19 @@
       logging.exception(err)
       return (None, None, None, None)
 
-  def RunAsConsoleUser(self, command, env=None, cwd=None, timeout=200):
-    """Runs the command as the console user on default desktop.
+  def RunAsStandardUser(self, command_line, env=None, cwd=None, timeout=30):
+    """Runs the command as the non-elevated logon user on default desktop.
 
     Args:
-      command: The command to run.
+      command_line: The command line string, includes all arguments.
       env: Environment variables to pass to command.
       cwd: Working directory for the command.
-      timeout: How long the child process should wait for UAC before timeout.
+      timeout: How long the child process should wait before timeout.
 
     Returns:
       (pid, exit_code, sdtout, stderr) tuple.
     """
-    return impersonate.RunAsConsoleUser(command, env, cwd, timeout)
+    return impersonate.RunAsStandardUser(command_line, env, cwd, timeout)
 
   def AnswerUpcomingUACPrompt(self,
                               actions,
diff --git a/chrome/updater/test/service/win/run_command_as_standard_user.py b/chrome/updater/test/service/win/run_command_as_standard_user.py
new file mode 100644
index 0000000..b552dc1c
--- /dev/null
+++ b/chrome/updater/test/service/win/run_command_as_standard_user.py
@@ -0,0 +1,83 @@
+# 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.
+
+# [VPYTHON:BEGIN]
+# python_version: "2"
+# wheel: <
+#   name: "infra/python/wheels/pywin32/${vpython_platform}"
+#    version: "version:224"
+# >
+# [VPYTHON:END]
+
+"""Run the given command as the standard user.
+
+All arguments provided to this program will be used to reconstruct the command
+line for the child process. For example,
+    vpython run_command_as_standard_user.py notepad "hello world.txt"
+will launch a process with command line:
+    notepad "hello world.txt"
+
+This command must be run as an elevated user.
+"""
+
+import distutils
+import logging
+import os
+import subprocess
+import sys
+
+import rpc_client
+import updater_test_service_control
+
+
+def LogToSTDERR(title, output):
+  if not output:
+    return
+
+  logging.error('%s %s starts %s', '=' * 30, title, '=' * 30)
+
+  # Directly dump the output to STDER so we don't have logging prefix each
+  # line, to make it easier to read.
+  sys.stderr.write(output)
+
+  logging.error('%s  %s ends  %s', '=' * 30, title, '=' * 30)
+
+
+def main():
+  if len(sys.argv) < 2:
+    logging.error('Must specify a command to run.')
+    sys.exit(-1)
+
+  # Find the location of the command. shutil.which() looks suitable for this,
+  # only if https://bugs.python.org/issue24505 is closed. For now, use the
+  # one from distutils module.
+  command = distutils.spawn.find_executable(sys.argv[1])
+  if not command:
+    logging.error('Cannot find command: %s', sys.argv[1])
+    sys.exit(-2)
+
+  # Command may be in relative path. Make it absolute so that the RPC server
+  # can find it.
+  command = os.path.abspath(command)
+
+  # RunAsStandardUser() takes a full command line string (as it is forwarded to
+  # the underlying win32 implementation). We have sys.argv, but the value is
+  # already processed by shell. It is possible that the reconstructed command
+  # line is skewed (for example, expansion of environment variable), but
+  # hopefully this works well enough in all real scenarios.
+  command_line = subprocess.list2cmdline([command] + sys.argv[2:])
+  logging.error('Full command line: %s', command_line)
+  with updater_test_service_control.OpenService():
+    pid, exit_code, stdout, stderr = rpc_client.RunAsStandardUser(command_line)
+    if pid is None:
+      logging.error('Failed to launch command: %s', command_line)
+      sys.exit(-3)
+    LogToSTDERR('STDOUT', stdout)
+    if exit_code != 0:
+      LogToSTDERR('STDERR', stderr)
+    sys.exit(exit_code)
+
+
+if __name__ == '__main__':
+  main()
diff --git a/chrome/updater/test/service/win/uac.py b/chrome/updater/test/service/win/uac.py
index 9772b163..498cbe09 100644
--- a/chrome/updater/test/service/win/uac.py
+++ b/chrome/updater/test/service/win/uac.py
@@ -5,7 +5,9 @@
 import logging
 import sys
 
-import winreg
+# TODO(crbug.com/1233612): We are still running with PY2, import winreg
+# directly once we switch to PY3.
+import _winreg as winreg
 
 import ui
 
diff --git a/chrome/updater/test/service/win/updater_test_service_control.py b/chrome/updater/test/service/win/updater_test_service_control.py
index 4fe955e..95676e969 100644
--- a/chrome/updater/test/service/win/updater_test_service_control.py
+++ b/chrome/updater/test/service/win/updater_test_service_control.py
@@ -6,11 +6,12 @@
 # python_version: "2.7"
 # wheel: <
 #   name: "infra/python/wheels/pywin32/${vpython_platform}"
-#    version: "version:227"
+#    version: "version:224"
 # >
 # [VPYTHON:END]
 
 
+import contextlib
 import logging
 import os
 import shutil
@@ -18,37 +19,22 @@
 import socket
 import sys
 import time
-import xmlrpclib
 
 import pywintypes
 import win32api
 import win32service
 import win32serviceutil
 
+import rpc_client
 
 _UPDATER_TEST_SERVICE_NAME = 'UpdaterTestService'
 
-# TODO(crbug.com/1233612): Query XML RPC server port once the server propgate
-# the value.
-_UPDATER_XML_RPC_PORT = 9090
-
 
 # Errors that might be raised when interacting with the service.
 _ServiceErrors = (OSError, pywintypes.error, win32api.error, win32service.error,
                   WindowsError)  # pylint: disable=undefined-variable
 
 
-def _TestXMLRPCServerConnection():
-  """Test that connection to the XML RPC server."""
-  proxy = xmlrpclib.ServerProxy('http://localhost:%s' % _UPDATER_XML_RPC_PORT)
-  try:
-    return 'hi' == proxy.echo('hi')
-  except (socket.error, socket.herror, socket.gaierror, socket.timeout) as err:
-    logging.error('Unable connect to XML RPC server')
-    logging.exception(err)
-    return False
-
-
 def _RunCommand(command, log_error=True):
   """Run a command and logs stdout/stderr if needed.
 
@@ -179,7 +165,7 @@
 
     command = [sys.executable, service_main, 'remove']
     if _RunCommand(command):
-      logging.info('Service [%s] uninstalled.', _UPDATER_TEST_SERVICE_NAME)
+      logging.error('Service [%s] uninstalled.', _UPDATER_TEST_SERVICE_NAME)
       return True
     else:
       logging.error('Failed to uninstall [%s].', _UPDATER_TEST_SERVICE_NAME)
@@ -211,7 +197,7 @@
       return False
 
     logging.error('Service %s started.', _UPDATER_TEST_SERVICE_NAME)
-    return _TestXMLRPCServerConnection()
+    return rpc_client.TestConnection()
   except _ServiceErrors as err:
     logging.error('Failed to start service.')
     logging.exception(err)
@@ -243,6 +229,18 @@
     return False
 
 
+@contextlib.contextmanager
+def OpenService():
+  """Open the service as a managed resource."""
+  try:
+    if InstallService() and StartService():
+      yield _UPDATER_TEST_SERVICE_NAME
+    else:
+      yield None
+  finally:
+    UninstallService()
+
+
 if __name__ == '__main__':
   if len(sys.argv) == 1:
     logging.error('Must provide an action.')
diff --git a/chromecast/android/lint-baseline.xml b/chromecast/android/lint-baseline.xml
index e282d54..12fd5a8 100644
--- a/chromecast/android/lint-baseline.xml
+++ b/chromecast/android/lint-baseline.xml
@@ -1,70 +1,68 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.0.1" client="cli" variant="all" version="4.0.1">
+<issues format="5" by="lint 7.0.0" client="cli" variant="all" version="4.0.1">
 
     <issue
-        id="InlinedApi"
-        message="Field requires API level 25 (current min is 21): `android.provider.Settings.Global#DEVICE_NAME`"
-        errorLine1="    private static final String DEVICE_NAME_SETTING_KEY = Settings.Global.DEVICE_NAME;"
-        errorLine2="                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        id="MissingVersion"
+        message="Should set `android:versionCode` to specify the application version">
+        <location
+            file="gen/chromecast/cast_shell_apk__lint/gen/cast_shell_manifest/AndroidManifest.xml"
+            line="2"/>
+    </issue>
+
+    <issue
+        id="MissingVersion"
+        message="Should set `android:versionName` to specify the application version">
+        <location
+            file="gen/chromecast/cast_shell_apk__lint/gen/cast_shell_manifest/AndroidManifest.xml"
+            line="2"/>
+    </issue>
+
+    <issue
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 23">
+        <location
+            file="../../chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java"
+            line="248"/>
+    </issue>
+
+    <issue
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 23">
+        <location
+            file="../../chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java"
+            line="380"/>
+    </issue>
+
+    <issue
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 23">
+        <location
+            file="../../chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/AudioSinkAudioTrackImpl.java"
+            line="479"/>
+    </issue>
+
+    <issue
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 23">
         <location
             file="../../chromecast/base/java/src/org/chromium/chromecast/base/CastSettingsManager.java"
-            line="37"
-            column="59"/>
+            line="151"/>
     </issue>
 
     <issue
-        id="InflateParams"
-        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
-        errorLine1="                                        .inflate(R.layout.cast_web_contents_activity, null);"
-        errorLine2="                                                                                      ~~~~">
+        id="ObsoleteSdkInt"
+        message="Unnecessary; SDK_INT is always >= 23">
         <location
-            file="../../chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsFragment.java"
-            line="68"
-            column="87"/>
-    </issue>
-
-    <issue
-        id="InflateParams"
-        message="Avoid passing `null` as the view root (needed to resolve layout parameters on the inflated layout&apos;s root element)"
-        errorLine1="                        .inflate(R.layout.cast_web_contents_activity, null),"
-        errorLine2="                                                                      ~~~~">
-        <location
-            file="../../chromecast/browser/android/apk/src/org/chromium/chromecast/shell/CastWebContentsView.java"
-            line="50"
-            column="71"/>
-    </issue>
-
-    <issue
-        id="MissingVersion"
-        message="Should set `android:versionCode` to specify the application version"
-        errorLine1="&lt;manifest package=&quot;org.chromium.chromecast.shell&quot; xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>"
-        errorLine2=" ~~~~~~~~">
-        <location
-            file="gen/chromecast/cast_shell_apk__lint/gen/cast_shell_manifest/AndroidManifest.xml"
-            line="2"
-            column="2"/>
-    </issue>
-
-    <issue
-        id="MissingVersion"
-        message="Should set `android:versionName` to specify the application version"
-        errorLine1="&lt;manifest package=&quot;org.chromium.chromecast.shell&quot; xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;>"
-        errorLine2=" ~~~~~~~~">
-        <location
-            file="gen/chromecast/cast_shell_apk__lint/gen/cast_shell_manifest/AndroidManifest.xml"
-            line="2"
-            column="2"/>
+            file="../../chromecast/media/cma/backend/android/java/src/org/chromium/chromecast/cma/backend/android/VolumeControl.java"
+            line="93"/>
     </issue>
 
     <issue
         id="Overdraw"
-        message="Possible overdraw: Root element paints background `#FFFFFF` with a theme that also paints a background (inferred theme is `@style/CastShellTheme`)"
-        errorLine1="    android:background=&quot;#FFFFFF&quot;"
-        errorLine2="    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+        message="Possible overdraw: Root element paints background `#FFFFFF` with a theme that also paints a background (inferred theme is `@style/CastShellTheme`)">
         <location
             file="../../chromecast/browser/android/apk/res/layout/cast_web_contents_activity.xml"
-            line="12"
-            column="5"/>
+            line="12"/>
     </issue>
 
     <issue
diff --git a/chromecast/android/lint-suppressions.xml b/chromecast/android/lint-suppressions.xml
index 6b3d7959..19454b0 100644
--- a/chromecast/android/lint-suppressions.xml
+++ b/chromecast/android/lint-suppressions.xml
@@ -2,14 +2,15 @@
 <lint>
   <!-- Ignore all lint errors in chrome code. -->
   <issue id="all">
-    <ignore regexp="../../base/"/>
-    <ignore regexp="../../components/"/>
-    <ignore regexp="../../content/"/>
-    <ignore regexp="../../device/"/>
-    <ignore regexp="../../media/"/>
-    <ignore regexp="../../net/"/>
-    <ignore regexp="../../services/"/>
-    <ignore regexp="../../ui/"/>
+    <ignore regexp="\.\./\.\./base/"/>
+    <ignore regexp="\.\./\.\./components/"/>
+    <ignore regexp="\.\./\.\./content/"/>
+    <ignore regexp="\.\./\.\./device/"/>
+    <ignore regexp="\.\./\.\./media/"/>
+    <ignore regexp="\.\./\.\./net/"/>
+    <ignore regexp="\.\./\.\./services/"/>
+    <ignore regexp="\.\./\.\./third_party/"/>
+    <ignore regexp="\.\./\.\./ui/"/>
   </issue>
   <!-- The following cast-specific suppressions have been migrated from
        //build/android/lint/suppressions.xml -->
diff --git a/chromecast/browser/webview/client/webview.cc b/chromecast/browser/webview/client/webview.cc
index 9cb49be0..c17dfcf 100644
--- a/chromecast/browser/webview/client/webview.cc
+++ b/chromecast/browser/webview/client/webview.cc
@@ -129,15 +129,17 @@
 }
 
 void WebviewClient::AllocateBuffers(const InitParams& params) {
-  static wl_buffer_listener buffer_listener = {BufferReleaseCallback};
   for (size_t i = 0; i < params.num_buffers; ++i) {
-    auto buffer_callback = std::make_unique<BufferCallback>();
-    auto buffer = CreateBuffer(size_, params.drm_format, params.bo_usage,
-                               &buffer_listener, buffer_callback.get());
+    auto buffer =
+        CreateBuffer(size_, params.drm_format, params.bo_usage, false);
     if (!buffer) {
       LOG(ERROR) << "Failed to create buffer";
       return;
     }
+    static wl_buffer_listener buffer_listener = {BufferReleaseCallback};
+    auto buffer_callback = std::make_unique<BufferCallback>();
+    wl_buffer_add_listener(buffer->buffer.get(), &buffer_listener,
+                           buffer_callback.get());
     buffer_callback->client = this;
     buffer_callback->buffer = buffer.get();
     buffer_callbacks_.push_back(std::move(buffer_callback));
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 434e871..cc2aeae5 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -1004,6 +1004,18 @@
       <message name="IDS_DIAGNOSTICS_EID_LABEL" desc="The label for a Cellular network's EID.">
         EID
       </message>
+      <message name="IDS_DIAGNOSTICS_FAILED_TEST_TEXT" desc="The text that displays the test that failed.">
+        <ph name="TEST_NAME">$1<ex>Stress</ex></ph> test failed
+      </message>
+      <message name="IDS_DIAGNOSTICS_LOCAL_NETWORK_GROUP_LABEL" desc="The label for the group of tests related to the device's local network.">
+        Local Network
+      </message>
+      <message name="IDS_DIAGNOSTICS_NAME_RESOLUTION_GROUP_LABEL" desc="The label for the group of tests  about the device's network DNS (domain name servers).">
+        Name Resolution
+      </message>
+      <message name="IDS_DIAGNOSTICS_INTERNET_CONNECTIVITY_GROUP_LABEL" desc="The label for the group of tests related to internet connectivity.">
+        Internet Connectivity
+      </message>
 
       <!-- Input diagnostics -->
       <message name="IDS_INPUT_DIAGNOSTICS_RUN_TEST" desc="Text for the button that runs a test for a specific input device">
@@ -1721,6 +1733,37 @@
       <message name="IDS_NETWORK_DIAGNOSTICS_ARC_DNS_RESOLUTION" desc="Label for Network diagnostics `ARC DNS resolution` test. This test ensures that the Domain Name Server (DNS) can resolve network requests inside ARC.">
         (Android) DNS resolution
       </message>
+      <!-- TODO(ashleydp): Remove translateable false for all network technology when display text confirmed. -->
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_CDMA1XRTT" desc="Label for Cellular network technology `CDMA1XRTT`.">
+        CDMA1XRTT
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_EDGE" desc="Label for Cellular network technology `EDGE`.">
+        EDGE
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_EVDO" desc="Label for Cellular network technology `EVDO`.">
+        EVDO
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_GPRS" desc="Label for Cellular network technology `GPRS`.">
+        GPRS
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_GSM" desc="Label for Cellular network technology `GMS`.">
+        GSM
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_HSPA" desc="Label for Cellular network technology `HSPA`.">
+        HSPA
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_HSPA_PLUS" desc="Label for Cellular network technology `HSPAPlus`.">
+        HSPAPlus
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_LTE" desc="Label for Cellular network technology `LTE`.">
+        LTE
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_LTE_ADVANCED" desc="Label for Cellular network technology `LTEAdvanced`.">
+        LTEAdvanced
+      </message>
+      <message translateable="false" name="IDS_NETWORK_DIAGNOSTICS_CELLULAR_UMTS" desc="Label for Cellular network technology `UMTS`.">
+        UMTS
+      </message>
 
       <!-- Personalization App -->
       <message name="IDS_PERSONALIZATION_APP_TITLE" desc="Name of the system web app for personalizing ChromeOS.">
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_FAILED_TEST_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_FAILED_TEST_TEXT.png.sha1
new file mode 100644
index 0000000..54d4175
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_FAILED_TEST_TEXT.png.sha1
@@ -0,0 +1 @@
+584cb9d47a2d01dd7f4f46ffe863742f8e420109
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_INTERNET_CONNECTIVITY_GROUP_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_INTERNET_CONNECTIVITY_GROUP_LABEL.png.sha1
new file mode 100644
index 0000000..cf3765c7
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_INTERNET_CONNECTIVITY_GROUP_LABEL.png.sha1
@@ -0,0 +1 @@
+401c3bc09fb2e8e7dbbad5dda714f038e76b376b
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LOCAL_NETWORK_GROUP_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LOCAL_NETWORK_GROUP_LABEL.png.sha1
new file mode 100644
index 0000000..cf3765c7
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LOCAL_NETWORK_GROUP_LABEL.png.sha1
@@ -0,0 +1 @@
+401c3bc09fb2e8e7dbbad5dda714f038e76b376b
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_NAME_RESOLUTION_GROUP_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_NAME_RESOLUTION_GROUP_LABEL.png.sha1
new file mode 100644
index 0000000..cf3765c7
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_NAME_RESOLUTION_GROUP_LABEL.png.sha1
@@ -0,0 +1 @@
+401c3bc09fb2e8e7dbbad5dda714f038e76b376b
\ No newline at end of file
diff --git a/components/browsing_data/content/BUILD.gn b/components/browsing_data/content/BUILD.gn
index 65293ae7..a40fb7d 100644
--- a/components/browsing_data/content/BUILD.gn
+++ b/components/browsing_data/content/BUILD.gn
@@ -50,7 +50,6 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "appcache_helper_unittest.cc",
     "browsing_data_helper_unittest.cc",
     "cache_storage_helper_unittest.cc",
     "cookie_helper_unittest.cc",
diff --git a/components/browsing_data/content/appcache_helper_unittest.cc b/components/browsing_data/content/appcache_helper_unittest.cc
deleted file mode 100644
index 581c8a1..0000000
--- a/components/browsing_data/content/appcache_helper_unittest.cc
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/browsing_data/content/appcache_helper.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/containers/contains.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/bind.h"
-#include "build/build_config.h"
-#include "content/public/browser/storage_partition.h"
-#include "content/public/browser/storage_usage_info.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace browsing_data {
-
-class CannedAppCacheHelperTest : public testing::Test {
- public:
-  CannedAppCacheHelperTest()
-      : task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD) {}
-
-  void TearDown() override {
-    // Make sure we run all pending tasks on IO thread before testing
-    // browser context is destructed.
-    content::RunAllPendingInMessageLoop(content::BrowserThread::IO);
-    task_environment_.RunUntilIdle();
-  }
-
- protected:
-  scoped_refptr<CannedAppCacheHelper> CreateHelper() {
-    return base::MakeRefCounted<CannedAppCacheHelper>(
-        browser_context_.GetDefaultStoragePartition()->GetAppCacheService());
-  }
-
-  static bool ContainsOrigin(
-      const std::list<content::StorageUsageInfo>& collection,
-      const url::Origin& origin) {
-    return std::find_if(collection.begin(), collection.end(),
-                        [&](const content::StorageUsageInfo& info) {
-                          return info.origin == origin;
-                        }) != collection.end();
-  }
-
-  content::BrowserTaskEnvironment task_environment_;
-  content::TestBrowserContext browser_context_;
-};
-
-TEST_F(CannedAppCacheHelperTest, SetInfo) {
-  GURL manifest1("http://example1.com/manifest.xml");
-  GURL manifest2("http://example2.com/path1/manifest.xml");
-  GURL manifest3("http://example2.com/path2/manifest.xml");
-
-  auto helper = CreateHelper();
-  helper->Add(url::Origin::Create(manifest1));
-  helper->Add(url::Origin::Create(manifest2));
-  helper->Add(url::Origin::Create(manifest3));
-
-  std::list<content::StorageUsageInfo> collection;
-  base::RunLoop run_loop;
-  helper->StartFetching(base::BindLambdaForTesting(
-      [&](const std::list<content::StorageUsageInfo>& list) {
-        collection = list;
-        run_loop.Quit();
-      }));
-  run_loop.Run();
-
-  ASSERT_EQ(2u, collection.size());
-  EXPECT_TRUE(ContainsOrigin(collection, url::Origin::Create(manifest1)));
-  EXPECT_TRUE(ContainsOrigin(collection, url::Origin::Create(manifest2)));
-  for (const auto& info : collection) {
-    EXPECT_EQ(0, info.total_size_bytes);
-    EXPECT_EQ(base::Time(), info.last_modified);
-  }
-}
-
-TEST_F(CannedAppCacheHelperTest, Unique) {
-  GURL manifest("http://example.com/manifest.xml");
-
-  auto helper = CreateHelper();
-  helper->Add(url::Origin::Create(manifest));
-  helper->Add(url::Origin::Create(manifest));
-
-  std::list<content::StorageUsageInfo> collection;
-  base::RunLoop run_loop;
-  helper->StartFetching(base::BindLambdaForTesting(
-      [&](const std::list<content::StorageUsageInfo>& list) {
-        collection = list;
-        run_loop.Quit();
-      }));
-  run_loop.Run();
-
-  ASSERT_EQ(1u, collection.size());
-  EXPECT_TRUE(ContainsOrigin(collection, url::Origin::Create(manifest)));
-}
-
-TEST_F(CannedAppCacheHelperTest, Empty) {
-  GURL manifest("http://example.com/manifest.xml");
-
-  auto helper = CreateHelper();
-
-  ASSERT_TRUE(helper->empty());
-  helper->Add(url::Origin::Create(manifest));
-  ASSERT_FALSE(helper->empty());
-  helper->Reset();
-  ASSERT_TRUE(helper->empty());
-}
-
-TEST_F(CannedAppCacheHelperTest, Delete) {
-  GURL manifest1("http://example.com/manifest1.xml");
-  GURL manifest2("http://foo.example.com/manifest2.xml");
-  GURL manifest3("http://bar.example.com/manifest3.xml");
-
-  auto helper = CreateHelper();
-
-  EXPECT_TRUE(helper->empty());
-  helper->Add(url::Origin::Create(manifest1));
-  helper->Add(url::Origin::Create(manifest2));
-  helper->Add(url::Origin::Create(manifest3));
-  EXPECT_FALSE(helper->empty());
-  EXPECT_EQ(3u, helper->GetCount());
-  helper->DeleteAppCaches(url::Origin::Create(manifest2));
-  EXPECT_EQ(2u, helper->GetCount());
-  EXPECT_FALSE(
-      base::Contains(helper->GetOrigins(), url::Origin::Create(manifest2)));
-}
-
-TEST_F(CannedAppCacheHelperTest, IgnoreExtensionsAndDevTools) {
-  GURL manifest1("chrome-extension://abcdefghijklmnopqrstuvwxyz/manifest.xml");
-  GURL manifest2("devtools://abcdefghijklmnopqrstuvwxyz/manifest.xml");
-
-  auto helper = CreateHelper();
-
-  ASSERT_TRUE(helper->empty());
-  helper->Add(url::Origin::Create(manifest1));
-  ASSERT_TRUE(helper->empty());
-  helper->Add(url::Origin::Create(manifest2));
-  ASSERT_TRUE(helper->empty());
-}
-
-}  // namespace browsing_data
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index cafcfad7..b2afc73 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "3.33",
-  "log_list_timestamp": "2021-09-18T01:33:46Z",
+  "version": "3.35",
+  "log_list_timestamp": "2021-09-20T01:33:49Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/cronet/android/sample/AndroidManifest.xml b/components/cronet/android/sample/AndroidManifest.xml
index 2a7ded8..1a722e5 100644
--- a/components/cronet/android/sample/AndroidManifest.xml
+++ b/components/cronet/android/sample/AndroidManifest.xml
@@ -30,6 +30,7 @@
             android:authorities="org.chromium.cronet_sample_apk.androidx-startup"
             android:name="androidx.startup.InitializationProvider"
             android:exported="false"
+            tools:replace="android:authorities"
             tools:node="remove">
         </provider>
     </application>
diff --git a/components/embedder_support/BUILD.gn b/components/embedder_support/BUILD.gn
index b6c2fd4..b7a4855 100644
--- a/components/embedder_support/BUILD.gn
+++ b/components/embedder_support/BUILD.gn
@@ -60,6 +60,7 @@
     "//testing/gtest",
     "//third_party/blink/public/common:headers",
     "//third_party/blink/public/mojom:mojom_platform_headers",
+    "//third_party/re2",
   ]
 
   if (is_android) {
diff --git a/components/embedder_support/DEPS b/components/embedder_support/DEPS
index cac2e83..8eb9c3ab 100644
--- a/components/embedder_support/DEPS
+++ b/components/embedder_support/DEPS
@@ -9,4 +9,5 @@
   "+content/public/common",
   "+net",
   "+third_party/blink/public/common",
+  "+third_party/re2",
 ]
diff --git a/components/embedder_support/user_agent_utils.cc b/components/embedder_support/user_agent_utils.cc
index dfa5022f..516504c 100644
--- a/components/embedder_support/user_agent_utils.cc
+++ b/components/embedder_support/user_agent_utils.cc
@@ -5,11 +5,13 @@
 #include "components/embedder_support/user_agent_utils.h"
 
 #include "base/command_line.h"
+#include "base/feature_list.h"
 #include "base/no_destructor.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/stringprintf.h"
 #include "base/system/sys_info.h"
+#include "base/version.h"
 #include "build/branding_buildflags.h"
 #include "build/build_config.h"
 #include "components/embedder_support/switches.h"
@@ -31,9 +33,12 @@
 
 namespace embedder_support {
 
-#if defined(OS_WIN)
 namespace {
 
+constexpr char kMajorVersion100[] = "100";
+
+#if defined(OS_WIN)
+
 // The registry key where the UniversalApiContract version value can be read
 // from.
 constexpr wchar_t kWindowsRuntimeWellKnownContractsRegKeyName[] =
@@ -109,10 +114,68 @@
                        base::NumberToString(minor_version), ".0"});
 }
 
-}  // namespace
 #endif  // defined(OS_WIN)
 
+const std::string& GetM100VersionNumber() {
+  static const base::NoDestructor<std::string> m100_version_number([] {
+    base::Version version(version_info::GetVersionNumber());
+    std::string version_str(kMajorVersion100);
+    const std::vector<uint32_t>& components = version.components();
+    // Rest of the version string remains the same.
+    for (size_t i = 1; i < components.size(); ++i) {
+      version_str.append(".");
+      version_str.append(base::NumberToString(components[i]));
+    }
+    return version_str;
+  }());
+  return *m100_version_number;
+}
+
+const blink::UserAgentBrandList GetUserAgentBrandList(
+    const std::string& major_version) {
+  int major_version_number;
+  base::StringToInt(major_version, &major_version_number);
+  absl::optional<std::string> brand;
+#if !BUILDFLAG(CHROMIUM_BRANDING)
+  brand = version_info::GetProductName();
+#endif
+  absl::optional<std::string> maybe_param_override =
+      base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
+                                             "brand_override");
+  if (maybe_param_override->empty())
+    maybe_param_override = absl::nullopt;
+
+  return GenerateBrandVersionList(major_version_number, brand, major_version,
+                                  maybe_param_override);
+}
+
+const blink::UserAgentBrandList& GetUserAgentBrandList() {
+  static const base::NoDestructor<blink::UserAgentBrandList> brand_list(
+      GetUserAgentBrandList(version_info::GetMajorVersionNumber()));
+  return *brand_list;
+}
+
+const blink::UserAgentBrandList& GetForcedM100UserAgentBrandList() {
+  static const base::NoDestructor<blink::UserAgentBrandList> brand_list(
+      GetUserAgentBrandList(kMajorVersion100));
+  return *brand_list;
+}
+
+const blink::UserAgentBrandList& GetBrandVersionList() {
+  if (base::FeatureList::IsEnabled(
+          blink::features::kForceMajorVersion100InUserAgent))
+    return GetForcedM100UserAgentBrandList();
+
+  return GetUserAgentBrandList();
+}
+
+}  // namespace
+
 std::string GetProduct() {
+  if (base::FeatureList::IsEnabled(
+          blink::features::kForceMajorVersion100InUserAgent))
+    return "Chrome/" + GetM100VersionNumber();
+
   return version_info::GetProductNameAndVersionForUserAgent();
 }
 
@@ -140,7 +203,10 @@
   return content::GetReducedUserAgent(
       base::CommandLine::ForCurrentProcess()->HasSwitch(
           switches::kUseMobileUserAgent),
-      version_info::GetMajorVersionNumber());
+      base::FeatureList::IsEnabled(
+          blink::features::kForceMajorVersion100InUserAgent)
+          ? kMajorVersion100
+          : version_info::GetMajorVersionNumber());
 }
 
 // Generate a pseudo-random permutation of the following brand/version pairs:
@@ -196,28 +262,6 @@
   return greased_brand_version_list;
 }
 
-const blink::UserAgentBrandList& GetBrandVersionList() {
-  static const base::NoDestructor<blink::UserAgentBrandList>
-      greased_brand_version_list([] {
-        int major_version_number;
-        std::string major_version = version_info::GetMajorVersionNumber();
-        base::StringToInt(major_version, &major_version_number);
-        absl::optional<std::string> brand;
-#if !BUILDFLAG(CHROMIUM_BRANDING)
-        brand = version_info::GetProductName();
-#endif
-        absl::optional<std::string> maybe_param_override =
-            base::GetFieldTrialParamValueByFeature(features::kGreaseUACH,
-                                                   "brand_override");
-        if (maybe_param_override->empty())
-          maybe_param_override = absl::nullopt;
-
-        return GenerateBrandVersionList(major_version_number, brand,
-                                        major_version, maybe_param_override);
-      }());
-  return *greased_brand_version_list;
-}
-
 // TODO(crbug.com/1103047): This can be removed/re-refactored once we use
 // "macOS" by default
 std::string GetPlatformForUAMetadata() {
@@ -232,7 +276,10 @@
   blink::UserAgentMetadata metadata;
 
   metadata.brand_version_list = GetBrandVersionList();
-  metadata.full_version = version_info::GetVersionNumber();
+  metadata.full_version = base::FeatureList::IsEnabled(
+                              blink::features::kForceMajorVersion100InUserAgent)
+                              ? GetM100VersionNumber()
+                              : version_info::GetVersionNumber();
   metadata.platform = GetPlatformForUAMetadata();
   metadata.architecture = content::GetLowEntropyCpuArchitecture();
   metadata.model = content::BuildModelInfo();
@@ -265,11 +312,10 @@
                                  const blink::UserAgentMetadata& metadata,
                                  bool override_in_new_tabs) {
   const char kLinuxInfoStr[] = "X11; Linux x86_64";
-  std::string product = version_info::GetProductNameAndVersionForUserAgent();
 
   blink::UserAgentOverride spoofed_ua;
   spoofed_ua.ua_string_override =
-      content::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, product);
+      content::BuildUserAgentFromOSAndProduct(kLinuxInfoStr, GetProduct());
   spoofed_ua.ua_metadata_override = metadata;
   spoofed_ua.ua_metadata_override->platform = "Linux";
   spoofed_ua.ua_metadata_override->platform_version =
diff --git a/components/embedder_support/user_agent_utils_unittest.cc b/components/embedder_support/user_agent_utils_unittest.cc
index 4a7226a..caa4fbd2 100644
--- a/components/embedder_support/user_agent_utils_unittest.cc
+++ b/components/embedder_support/user_agent_utils_unittest.cc
@@ -13,12 +13,15 @@
 #include "base/test/gtest_util.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/version.h"
 #include "build/build_config.h"
 #include "components/version_info/version_info.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/user_agent.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
+#include "third_party/re2/src/re2/re2.h"
 
 #if defined(USE_X11) || defined(USE_OZONE)
 #include <sys/utsname.h>
@@ -39,6 +42,12 @@
 
 namespace {
 
+// A regular expression that matches Chrome/{major_version}.{minor_version} in
+// the User-Agent string, where the first capture is the {major_version} and the
+// second capture is the {minor_version}.
+static constexpr char kChromeProductVersionRegex[] =
+    "Chrome/([0-9]+)\\.([0-9]+\\.[0-9]+\\.[0-9]+)";
+
 void CheckUserAgentStringOrdering(bool mobile_device) {
   std::vector<std::string> pieces;
 
@@ -265,7 +274,37 @@
 
 }  // namespace
 
-TEST(UserAgentUtilsTest, UserAgentStringOrdering) {
+class UserAgentUtilsTest : public testing::Test,
+                           public testing::WithParamInterface<bool> {
+ public:
+  void SetUp() override {
+    if (ForceMajorVersionTo100())
+      scoped_feature_list_.InitAndEnableFeature(
+          blink::features::kForceMajorVersion100InUserAgent);
+  }
+
+  bool ForceMajorVersionTo100() { return GetParam(); }
+
+  std::string M100VersionNumber() {
+    const base::Version version = version_info::GetVersion();
+    std::string m100_version("100");
+    // The rest of the version after the major version string is the same.
+    for (size_t i = 1; i < version.components().size(); ++i) {
+      m100_version.append(".");
+      m100_version.append(base::NumberToString(version.components()[i]));
+    }
+    return m100_version;
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_CASE_P(All,
+                        UserAgentUtilsTest,
+                        /*force_major_version_to_M100*/ testing::Bool());
+
+TEST_P(UserAgentUtilsTest, UserAgentStringOrdering) {
 #if defined(OS_ANDROID)
   const char* const kArguments[] = {"chrome"};
   base::test::ScopedCommandLine scoped_command_line;
@@ -285,7 +324,7 @@
 #endif
 }
 
-TEST(UserAgentUtilsTest, UserAgentStringReduced) {
+TEST_P(UserAgentUtilsTest, UserAgentStringReduced) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(blink::features::kReduceUserAgent);
 
@@ -296,6 +335,10 @@
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
   command_line->InitFromArgv(1, kArguments);
+  const std::string major_version_number =
+      version_info::GetMajorVersionNumber();
+  const char* const major_version =
+      ForceMajorVersionTo100() ? "100" : major_version_number.c_str();
 
   // Verify the mobile user agent string is not returned when not using a mobile
   // user agent.
@@ -306,8 +349,7 @@
     EXPECT_EQ(buffer,
               base::StringPrintf(content::frozen_user_agent_strings::kAndroid,
                                  content::GetUnifiedPlatform().c_str(),
-                                 version_info::GetMajorVersionNumber().c_str(),
-                                 device_compat.c_str()));
+                                 major_version, device_compat.c_str()));
   }
 
   // Verify the mobile user agent string is returned when using a mobile user
@@ -320,8 +362,7 @@
     EXPECT_EQ(buffer,
               base::StringPrintf(content::frozen_user_agent_strings::kAndroid,
                                  content::GetUnifiedPlatform().c_str(),
-                                 version_info::GetMajorVersionNumber().c_str(),
-                                 device_compat.c_str()));
+                                 major_version, device_compat.c_str()));
   }
 #else
   {
@@ -329,17 +370,20 @@
     EXPECT_EQ(buffer, base::StringPrintf(
                           content::frozen_user_agent_strings::kDesktop,
                           content::GetUnifiedPlatform().c_str(),
-                          version_info::GetMajorVersionNumber().c_str()));
+                          ForceMajorVersionTo100()
+                              ? "100"
+                              : version_info::GetMajorVersionNumber().c_str()));
   }
 #endif
 
   EXPECT_EQ(GetUserAgent(), GetReducedUserAgent());
 }
 
-TEST(UserAgentUtilsTest, UserAgentMetadata) {
+TEST_P(UserAgentUtilsTest, UserAgentMetadata) {
   auto metadata = GetUserAgentMetadata();
 
-  std::string major_version = version_info::GetMajorVersionNumber();
+  const std::string major_version =
+      ForceMajorVersionTo100() ? "100" : version_info::GetMajorVersionNumber();
 
   // According to spec, Sec-CH-UA should contain what project the browser is
   // based on (i.e. Chromium in this case) as well as the actual product.
@@ -349,7 +393,7 @@
   const blink::UserAgentBrandVersion chromium_brand_version = {"Chromium",
                                                                major_version};
   const blink::UserAgentBrandVersion product_brand_version = {
-      version_info::GetProductName(), version_info::GetMajorVersionNumber()};
+      version_info::GetProductName(), major_version};
   bool contains_chromium_brand_version = false;
   bool contains_product_brand_version = false;
 
@@ -365,7 +409,10 @@
   EXPECT_TRUE(contains_chromium_brand_version);
   EXPECT_TRUE(contains_product_brand_version);
 
-  EXPECT_EQ(metadata.full_version, version_info::GetVersionNumber());
+  const std::string expected_version_number =
+      ForceMajorVersionTo100() ? M100VersionNumber()
+                               : version_info::GetVersionNumber();
+  EXPECT_EQ(metadata.full_version, expected_version_number);
 
 #if defined(OS_WIN)
   if (base::win::GetVersion() < base::win::Version::WIN10) {
@@ -393,7 +440,7 @@
   EXPECT_EQ(metadata.bitness, content::GetLowEntropyCpuBitness());
 }
 
-TEST(UserAgentUtilsTest, GenerateBrandVersionList) {
+TEST_P(UserAgentUtilsTest, GenerateBrandVersionList) {
   blink::UserAgentMetadata metadata;
 
   metadata.brand_version_list =
@@ -427,4 +474,28 @@
       GenerateBrandVersionList(-1, absl::nullopt, "99", absl::nullopt));
 }
 
+TEST_P(UserAgentUtilsTest, GetProduct) {
+  const std::string product = GetProduct();
+  std::string major_version;
+  EXPECT_TRUE(
+      re2::RE2::FullMatch(product, kChromeProductVersionRegex, &major_version));
+  if (ForceMajorVersionTo100())
+    EXPECT_EQ(major_version, "100");
+  else
+    EXPECT_EQ(major_version, version_info::GetMajorVersionNumber());
+}
+
+TEST_P(UserAgentUtilsTest, GetUserAgent) {
+  const std::string ua = GetUserAgent();
+  std::string major_version;
+  std::string minor_version;
+  EXPECT_TRUE(re2::RE2::PartialMatch(ua, kChromeProductVersionRegex,
+                                     &major_version, &minor_version));
+  if (ForceMajorVersionTo100())
+    EXPECT_EQ(major_version, "100");
+  else
+    EXPECT_EQ(major_version, version_info::GetMajorVersionNumber());
+  EXPECT_NE(minor_version, "0.0.0");
+}
+
 }  // namespace embedder_support
diff --git a/components/exo/wayland/BUILD.gn b/components/exo/wayland/BUILD.gn
index 10b987e..134b02ad 100644
--- a/components/exo/wayland/BUILD.gn
+++ b/components/exo/wayland/BUILD.gn
@@ -172,6 +172,11 @@
       "zcr_notification_shell.h",
       "zcr_remote_shell.cc",
       "zcr_remote_shell.h",
+      "zcr_remote_shell_event_mapping.h",
+      "zcr_remote_shell_impl.cc",
+      "zcr_remote_shell_impl.h",
+      "zcr_remote_shell_v2.cc",
+      "zcr_remote_shell_v2.h",
       "zcr_stylus_tools.cc",
       "zcr_stylus_tools.h",
       "zwp_input_timestamps_manager.cc",
diff --git a/components/exo/wayland/clients/client_helper.cc b/components/exo/wayland/clients/client_helper.cc
index 88dbe2f..bea8ab66 100644
--- a/components/exo/wayland/clients/client_helper.cc
+++ b/components/exo/wayland/clients/client_helper.cc
@@ -83,6 +83,7 @@
 DEFAULT_DELETER(zcr_keyboard_extension_v1, zcr_keyboard_extension_v1_destroy)
 DEFAULT_DELETER(zcr_notification_shell_v1, zcr_notification_shell_v1_destroy)
 DEFAULT_DELETER(zcr_remote_shell_v1, zcr_remote_shell_v1_destroy)
+DEFAULT_DELETER(zcr_remote_shell_v2, zcr_remote_shell_v2_destroy)
 DEFAULT_DELETER(zcr_stylus_tools_v1, zcr_stylus_tools_v1_destroy)
 DEFAULT_DELETER(zcr_text_input_extension_v1,
                 zcr_text_input_extension_v1_destroy)
diff --git a/components/exo/wayland/clients/client_helper.h b/components/exo/wayland/clients/client_helper.h
index 0f39067..e490317 100644
--- a/components/exo/wayland/clients/client_helper.h
+++ b/components/exo/wayland/clients/client_helper.h
@@ -23,6 +23,7 @@
 #include <presentation-time-client-protocol.h>
 #include <relative-pointer-unstable-v1-client-protocol.h>
 #include <remote-shell-unstable-v1-client-protocol.h>
+#include <remote-shell-unstable-v2-client-protocol.h>
 #include <secure-output-unstable-v1-client-protocol.h>
 #include <stylus-tools-unstable-v1-client-protocol.h>
 #include <stylus-unstable-v2-client-protocol.h>
@@ -101,6 +102,7 @@
 DEFAULT_DELETER_FDECL(zcr_keyboard_extension_v1)
 DEFAULT_DELETER_FDECL(zcr_notification_shell_v1)
 DEFAULT_DELETER_FDECL(zcr_remote_shell_v1)
+DEFAULT_DELETER_FDECL(zcr_remote_shell_v2)
 DEFAULT_DELETER_FDECL(zcr_stylus_tools_v1)
 DEFAULT_DELETER_FDECL(zcr_text_input_extension_v1)
 DEFAULT_DELETER_FDECL(zwp_pointer_gestures_v1)
diff --git a/components/exo/wayland/clients/test/client_version_test.cc b/components/exo/wayland/clients/test/client_version_test.cc
index 40c46f89..df04475 100644
--- a/components/exo/wayland/clients/test/client_version_test.cc
+++ b/components/exo/wayland/clients/test/client_version_test.cc
@@ -15,6 +15,7 @@
 #include <pointer-gestures-unstable-v1-server-protocol.h>
 #include <relative-pointer-unstable-v1-server-protocol.h>
 #include <remote-shell-unstable-v1-server-protocol.h>
+#include <remote-shell-unstable-v2-server-protocol.h>
 #include <secure-output-unstable-v1-server-protocol.h>
 #include <stylus-tools-unstable-v1-server-protocol.h>
 #include <stylus-unstable-v2-server-protocol.h>
@@ -81,6 +82,7 @@
   std::unique_ptr<zcr_keyboard_extension_v1> zcr_keyboard_extension_v1;
   std::unique_ptr<zcr_notification_shell_v1> zcr_notification_shell_v1;
   std::unique_ptr<zcr_remote_shell_v1> zcr_remote_shell_v1;
+  std::unique_ptr<zcr_remote_shell_v2> zcr_remote_shell_v2;
   std::unique_ptr<zcr_stylus_tools_v1> zcr_stylus_tools_v1;
   std::unique_ptr<zwp_pointer_gestures_v1> zwp_pointer_gestures_v1;
   std::unique_ptr<zwp_pointer_constraints_v1> zwp_pointer_constraints_v1;
@@ -170,6 +172,7 @@
           REGISTRY_CALLBACK(zcr_notification_shell_v1,
                             zcr_notification_shell_v1),
           REGISTRY_CALLBACK(zcr_remote_shell_v1, zcr_remote_shell_v1),
+          REGISTRY_CALLBACK(zcr_remote_shell_v2, zcr_remote_shell_v2),
           REGISTRY_CALLBACK(zcr_stylus_tools_v1, zcr_stylus_tools_v1),
           REGISTRY_CALLBACK(zcr_text_input_extension_v1,
                             zcr_text_input_extension_v1),
diff --git a/components/exo/wayland/compatibility_test/BUILD.gn b/components/exo/wayland/compatibility_test/BUILD.gn
index df9bef7c9..c128215 100644
--- a/components/exo/wayland/compatibility_test/BUILD.gn
+++ b/components/exo/wayland/compatibility_test/BUILD.gn
@@ -29,6 +29,7 @@
   "//third_party/wayland-protocols/unstable/keyboard/keyboard-extension-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/notification-shell/notification-shell-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml",
+  "//third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v2.xml",
   "//third_party/wayland-protocols/unstable/secure-output/secure-output-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/stylus/stylus-unstable-v2.xml",
   "//third_party/wayland-protocols/unstable/stylus-tools/stylus-tools-unstable-v1.xml",
diff --git a/components/exo/wayland/fuzzer/BUILD.gn b/components/exo/wayland/fuzzer/BUILD.gn
index 57435968..7825c81f 100644
--- a/components/exo/wayland/fuzzer/BUILD.gn
+++ b/components/exo/wayland/fuzzer/BUILD.gn
@@ -29,6 +29,7 @@
   "//third_party/wayland-protocols/unstable/keyboard/keyboard-extension-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/notification-shell/notification-shell-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v1.xml",
+  "//third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v2.xml",
   "//third_party/wayland-protocols/unstable/secure-output/secure-output-unstable-v1.xml",
   "//third_party/wayland-protocols/unstable/stylus/stylus-unstable-v2.xml",
   "//third_party/wayland-protocols/unstable/stylus-tools/stylus-tools-unstable-v1.xml",
diff --git a/components/exo/wayland/protocol/aura-shell.xml b/components/exo/wayland/protocol/aura-shell.xml
index d62531e5..51d652b2 100644
--- a/components/exo/wayland/protocol/aura-shell.xml
+++ b/components/exo/wayland/protocol/aura-shell.xml
@@ -24,7 +24,7 @@
     DEALINGS IN THE SOFTWARE.
   </copyright>
 
-  <interface name="zaura_shell" version="23">
+  <interface name="zaura_shell" version="24">
     <description summary="aura_shell">
       The global interface exposing aura shell capabilities is used to
       instantiate an interface extension for a wl_surface object.
@@ -108,6 +108,14 @@
       </description>
       <arg name="active_desk_index" type="int" summary="index of the active desk"/>
     </event>
+    <!-- Version 24 additions -->
+    <event name="activated" since="24">
+      <description summary="activated surface changed">
+	Notifies client that the activated surface changed.
+      </description>
+      <arg name="gained_active" type="object" interface="wl_surface" allow-null="true"/>
+      <arg name="lost_active" type="object" interface="wl_surface" allow-null="true"/>
+    </event>
   </interface>
 
   <interface name="zaura_surface" version="23">
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc
index 76e09ec6..157833d 100644
--- a/components/exo/wayland/server.cc
+++ b/components/exo/wayland/server.cc
@@ -21,6 +21,7 @@
 #include <presentation-time-server-protocol.h>
 #include <relative-pointer-unstable-v1-server-protocol.h>
 #include <remote-shell-unstable-v1-server-protocol.h>
+#include <remote-shell-unstable-v2-server-protocol.h>
 #include <secure-output-unstable-v1-server-protocol.h>
 #include <stylus-tools-unstable-v1-server-protocol.h>
 #include <stylus-unstable-v2-server-protocol.h>
@@ -78,6 +79,7 @@
 #include "components/exo/wayland/zcr_keyboard_extension.h"
 #include "components/exo/wayland/zcr_notification_shell.h"
 #include "components/exo/wayland/zcr_remote_shell.h"
+#include "components/exo/wayland/zcr_remote_shell_v2.h"
 #include "components/exo/wayland/zcr_stylus_tools.h"
 #include "components/exo/wayland/zwp_input_timestamps_manager.h"
 #include "components/exo/wayland/zwp_pointer_constraints.h"
@@ -221,6 +223,9 @@
   wl_global_create(wl_display_.get(), &zcr_remote_shell_v1_interface,
                    zcr_remote_shell_v1_interface.version,
                    remote_shell_data_.get(), bind_remote_shell);
+  wl_global_create(wl_display_.get(), &zcr_remote_shell_v2_interface,
+                   zcr_remote_shell_v2_interface.version,
+                   remote_shell_data_.get(), bind_remote_shell_v2);
 
   wl_global_create(wl_display_.get(), &zcr_stylus_tools_v1_interface, 1,
                    display_, bind_stylus_tools);
diff --git a/components/exo/wayland/zaura_shell.cc b/components/exo/wayland/zaura_shell.cc
index ec12f1a..d162b14 100644
--- a/components/exo/wayland/zaura_shell.cc
+++ b/components/exo/wayland/zaura_shell.cc
@@ -18,6 +18,8 @@
 #include "ash/wm/window_state.h"
 #include "base/strings/string_number_conversions.h"
 #include "build/chromeos_buildflags.h"
+#include "components/exo/display.h"
+#include "components/exo/shell_surface_base.h"
 #include "components/exo/wayland/server_util.h"
 #include "components/exo/wayland/wayland_display_observer.h"
 #include "components/exo/wayland/wl_output.h"
@@ -679,7 +681,7 @@
 class WaylandAuraShell : public ash::DesksController::Observer,
                          public ash::TabletModeObserver {
  public:
-  explicit WaylandAuraShell(wl_resource* aura_shell_resource)
+  WaylandAuraShell(wl_resource* aura_shell_resource, Display* display)
       : aura_shell_resource_(aura_shell_resource) {
     WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
     helper->AddTabletModeObserver(this);
@@ -697,6 +699,9 @@
         zaura_shell_send_bug_fix(aura_shell_resource_, bug_id);
       }
     }
+    display->seat()->SetFocusChangedCallback(
+        base::BindRepeating(&WaylandAuraShell::FocusedSurfaceChanged,
+                            weak_ptr_factory_.GetWeakPtr()));
 
     OnDesksChanged();
     OnDeskActivationChanged();
@@ -773,8 +778,34 @@
         ash::DesksController::Get()->GetActiveDeskIndex());
   }
 
+  void FocusedSurfaceChanged(Surface* gained_active_surface,
+                             Surface* lost_active_surface,
+                             bool has_focused_client) {
+    if (wl_resource_get_version(aura_shell_resource_) <
+        ZAURA_SHELL_ACTIVATED_SINCE_VERSION)
+      return;
+    if (gained_active_surface == lost_active_surface)
+      return;
+
+    wl_resource* gained_active_surface_resource =
+        gained_active_surface ? GetSurfaceResource(gained_active_surface)
+                              : nullptr;
+    wl_resource* lost_active_surface_resource =
+        lost_active_surface ? GetSurfaceResource(lost_active_surface) : nullptr;
+
+    wl_client* client = wl_resource_get_client(aura_shell_resource_);
+
+    zaura_shell_send_activated(aura_shell_resource_,
+                               gained_active_surface_resource,
+                               lost_active_surface_resource);
+
+    wl_client_flush(client);
+  }
+
   // The aura shell resource associated with observer.
   wl_resource* const aura_shell_resource_;
+
+  base::WeakPtrFactory<WaylandAuraShell> weak_ptr_factory_{this};
 };
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH))
 
@@ -815,7 +846,9 @@
 }
 
 const struct zaura_shell_interface aura_shell_implementation = {
-    aura_shell_get_aura_surface, aura_shell_get_aura_output};
+    aura_shell_get_aura_surface,
+    aura_shell_get_aura_output,
+};
 
 }  // namespace
 
@@ -828,8 +861,9 @@
                          std::min(version, kZAuraShellVersion), id);
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+  Display* display = static_cast<Display*>(data);
   SetImplementation(resource, &aura_shell_implementation,
-                    std::make_unique<WaylandAuraShell>(resource));
+                    std::make_unique<WaylandAuraShell>(resource, display));
 #else
   wl_resource_set_implementation(resource, &aura_shell_implementation, nullptr,
                                  nullptr);
diff --git a/components/exo/wayland/zaura_shell.h b/components/exo/wayland/zaura_shell.h
index 5e495dd..02b8456 100644
--- a/components/exo/wayland/zaura_shell.h
+++ b/components/exo/wayland/zaura_shell.h
@@ -18,7 +18,7 @@
 namespace exo {
 namespace wayland {
 
-constexpr uint32_t kZAuraShellVersion = 23;
+constexpr uint32_t kZAuraShellVersion = 24;
 
 // Adds bindings to the Aura Shell. Normally this implies Ash on ChromeOS
 // builds. On non-ChromeOS builds the protocol provides access to Aura windowing
diff --git a/components/exo/wayland/zcr_remote_shell.cc b/components/exo/wayland/zcr_remote_shell.cc
index 668adc39..9495622 100644
--- a/components/exo/wayland/zcr_remote_shell.cc
+++ b/components/exo/wayland/zcr_remote_shell.cc
@@ -2,1478 +2,142 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/exo/wayland/zcr_remote_shell.h"
-
-#include <remote-shell-unstable-v1-server-protocol.h>
-#include <wayland-server-core.h>
-#include <wayland-server-protocol-core.h>
-
-#include "ash/public/cpp/shell_window_ids.h"
-#include "ash/public/cpp/tablet_mode_observer.h"
 #include "ash/public/cpp/window_properties.h"
-#include "ash/shelf/shelf.h"
-#include "ash/shelf/shelf_layout_manager.h"
 #include "ash/shell.h"
 #include "ash/wm/desks/desks_util.h"
-#include "ash/wm/window_resizer.h"
-#include "ash/wm/window_state.h"
 #include "ash/wm/work_area_insets.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chromeos/ui/base/window_pin_type.h"
-#include "components/exo/client_controlled_shell_surface.h"
-#include "components/exo/display.h"
-#include "components/exo/input_method_surface.h"
-#include "components/exo/notification_surface.h"
-#include "components/exo/shell_surface.h"
-#include "components/exo/shell_surface_base.h"
-#include "components/exo/shell_surface_util.h"
-#include "components/exo/surface_delegate.h"
-#include "components/exo/toast_surface.h"
 #include "components/exo/wayland/server_util.h"
-#include "components/exo/wayland/wayland_display_observer.h"
-#include "components/exo/wm_helper_chromeos.h"
-#include "ui/display/display_observer.h"
-#include "ui/display/screen.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/window/caption_button_types.h"
-#include "ui/wm/core/coordinate_conversion.h"
-#include "ui/wm/core/window_animations.h"
-#include "ui/wm/public/activation_change_observer.h"
+#include "components/exo/wayland/zcr_remote_shell_impl.h"
 
 namespace exo {
 namespace wayland {
-
 namespace {
 
-namespace switches {
-
-// This flag can be used to emulate device scale factor for remote shell.
-constexpr char kForceRemoteShellScale[] = "force-remote-shell-scale";
-
-}  // namespace switches
-
-using chromeos::WindowStateType;
-
-// We don't send configure immediately after tablet mode switch
-// because layout can change due to orientation lock state or accelerometer.
-constexpr int kConfigureDelayAfterLayoutSwitchMs = 300;
-
-// Convert to 8.24 fixed format.
-int32_t To8_24Fixed(double value) {
-  constexpr int kDecimalBits = 24;
-  return static_cast<int32_t>(value * (1 << kDecimalBits));
-}
-
-uint32_t ResizeDirection(int component) {
-  switch (component) {
-    case HTCAPTION:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
-    case HTTOP:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
-    case HTTOPRIGHT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
-    case HTRIGHT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
-    case HTBOTTOMRIGHT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
-    case HTBOTTOM:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
-    case HTBOTTOMLEFT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
-    case HTLEFT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
-    case HTTOPLEFT:
-      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
-    default:
-      LOG(ERROR) << "Unknown component:" << component;
-      break;
-  }
-  NOTREACHED();
-  return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
-}
-
-// Returns the scale factor to be used by remote shell clients.
-double GetDefaultDeviceScaleFactor() {
-  // A flag used by VM to emulate a device scale for a particular board.
-  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(switches::kForceRemoteShellScale)) {
-    std::string value =
-        command_line->GetSwitchValueASCII(switches::kForceRemoteShellScale);
-    double scale = 1.0;
-    if (base::StringToDouble(value, &scale))
-      return std::max(1.0, scale);
-  }
-  return WMHelper::GetInstance()->GetDefaultDeviceScaleFactor();
-}
-
-// Scale the |child_bounds| in such a way that if it should fill the
-// |parent_size|'s width/height, it returns the |parent_size_in_pixel|'s
-// width/height.
-gfx::Rect ScaleBoundsToPixelSnappedToParent(
-    const gfx::Size& parent_size_in_pixel,
-    const gfx::Size& parent_size,
-    float device_scale_factor,
-    const gfx::Rect& child_bounds) {
-  int right = child_bounds.right();
-  int bottom = child_bounds.bottom();
-
-  int new_x = base::ClampRound(child_bounds.x() * device_scale_factor);
-  int new_y = base::ClampRound(child_bounds.y() * device_scale_factor);
-
-  int new_right = right == parent_size.width()
-                      ? parent_size_in_pixel.width()
-                      : base::ClampRound(right * device_scale_factor);
-
-  int new_bottom = bottom == parent_size.height()
-                       ? parent_size_in_pixel.height()
-                       : base::ClampRound(bottom * device_scale_factor);
-  return gfx::Rect(new_x, new_y, new_right - new_x, new_bottom - new_y);
-}
-
-void ScaleSkRegion(const SkRegion& src, float scale, SkRegion* dst) {
-  SkRegion::Iterator iter(src);
-  for (; !iter.done(); iter.next()) {
-    SkIRect r;
-    r.fLeft = base::ClampFloor(iter.rect().fLeft * scale);
-    r.fTop = base::ClampFloor(iter.rect().fTop * scale);
-    r.fRight = base::ClampCeil(iter.rect().fRight * scale);
-    r.fBottom = base::ClampCeil(iter.rect().fBottom * scale);
-    dst->op(r, SkRegion::kUnion_Op);
-  }
-}
-
-ash::ShelfLayoutManager* GetShelfLayoutManagerForDisplay(
-    const display::Display& display) {
-  auto* root = ash::Shell::GetRootWindowForDisplayId(display.id());
-  return ash::Shelf::ForWindow(root)->shelf_layout_manager();
-}
-
-int SystemUiVisibility(const display::Display& display) {
-  auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display);
-  switch (shelf_layout_manager->visibility_state()) {
-    case ash::SHELF_VISIBLE:
-      return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE;
-    case ash::SHELF_AUTO_HIDE:
-    case ash::SHELF_HIDDEN:
-      return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY;
-  }
-  NOTREACHED() << "Got unexpected shelf visibility state "
-               << shelf_layout_manager->visibility_state();
-  return 0;
-}
-
-int SystemUiBehavior(const display::Display& display) {
-  auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display);
-  switch (shelf_layout_manager->auto_hide_behavior()) {
-    case ash::ShelfAutoHideBehavior::kNever:
-      return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE;
-    case ash::ShelfAutoHideBehavior::kAlways:
-    case ash::ShelfAutoHideBehavior::kAlwaysHidden:
-      return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN;
-  }
-  NOTREACHED() << "Got unexpected shelf visibility behavior.";
-  return 0;
-}
-
-int Component(uint32_t direction) {
-  switch (direction) {
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE:
-      return HTNOWHERE;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP:
-      return HTTOP;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT:
-      return HTTOPRIGHT;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT:
-      return HTRIGHT;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT:
-      return HTBOTTOMRIGHT;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM:
-      return HTBOTTOM;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT:
-      return HTBOTTOMLEFT;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT:
-      return HTLEFT;
-    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT:
-      return HTTOPLEFT;
-    default:
-      VLOG(2) << "Unknown direction:" << direction;
-      break;
-  }
-  return HTNOWHERE;
-}
-
-uint32_t CaptionButtonMask(uint32_t mask) {
-  uint32_t caption_button_icon_mask = 0;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_BACK)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_BACK;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MENU)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MENU;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MINIMIZE)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MINIMIZE;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MAXIMIZE_RESTORE)
-    caption_button_icon_mask |= 1
-                                << views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CLOSE)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CLOSE;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_ZOOM)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_ZOOM;
-  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CENTER)
-    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CENTER;
-  return caption_button_icon_mask;
-}
-
-void MaybeApplyCTSHack(int layout_mode,
-                       const gfx::Size& size_in_pixel,
-                       gfx::Insets* insets_in_client_pixel,
-                       gfx::Insets* stable_insets_in_client_pixel) {
-  constexpr int kBadBottomInsets = 90;
-  if (layout_mode == ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET &&
-      size_in_pixel.width() == 3000 && size_in_pixel.height() == 2000 &&
-      stable_insets_in_client_pixel->bottom() == kBadBottomInsets) {
-    stable_insets_in_client_pixel->set_bottom(kBadBottomInsets + 1);
-    if (insets_in_client_pixel->bottom() == kBadBottomInsets)
-      insets_in_client_pixel->set_bottom(kBadBottomInsets + 1);
-  }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// remote_surface_interface:
-
-SurfaceFrameType RemoteShellSurfaceFrameType(uint32_t frame_type) {
-  switch (frame_type) {
-    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NONE:
-      return SurfaceFrameType::NONE;
-    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NORMAL:
-      return SurfaceFrameType::NORMAL;
-    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_SHADOW:
-      return SurfaceFrameType::SHADOW;
-    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_AUTOHIDE:
-      return SurfaceFrameType::AUTOHIDE;
-    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_OVERLAY:
-      return SurfaceFrameType::OVERLAY;
-    default:
-      VLOG(2) << "Unknown remote-shell frame type: " << frame_type;
-      return SurfaceFrameType::NONE;
-  }
-}
-
-void remote_surface_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
-void remote_surface_set_app_id(wl_client* client,
-                               wl_resource* resource,
-                               const char* app_id) {
-  GetUserDataAs<ShellSurfaceBase>(resource)->SetApplicationId(app_id);
-}
-
-void remote_surface_set_window_geometry(wl_client* client,
-                                        wl_resource* resource,
-                                        int32_t x,
-                                        int32_t y,
-                                        int32_t width,
-                                        int32_t height) {
-  // DEPRECATED - Use set_bounds to send bounds info with a display_id.
-  GetUserDataAs<ShellSurfaceBase>(resource)->SetGeometry(
-      gfx::Rect(x, y, width, height));
-}
-
-void remote_surface_set_orientation(wl_client* client,
-                                    wl_resource* resource,
-                                    int32_t orientation) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientation(
-      orientation == ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT
-          ? Orientation::PORTRAIT
-          : Orientation::LANDSCAPE);
-}
-
-void remote_surface_set_scale(wl_client* client,
-                              wl_resource* resource,
-                              wl_fixed_t scale) {
-  // DEPRECATED (b/141715728) - The server updates the client's scale.
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetScale(
-      wl_fixed_to_double(scale));
-}
-
-void remote_surface_set_rectangular_shadow_DEPRECATED(wl_client* client,
-                                                      wl_resource* resource,
-                                                      int32_t x,
-                                                      int32_t y,
-                                                      int32_t width,
-                                                      int32_t height) {
-  NOTREACHED();
-}
-
-void remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED(
-    wl_client* client,
-    wl_resource* resource,
-    wl_fixed_t opacity) {
-  NOTREACHED();
-}
-
-void remote_surface_set_title(wl_client* client,
-                              wl_resource* resource,
-                              const char* title) {
-  GetUserDataAs<ShellSurfaceBase>(resource)->SetTitle(
-      std::u16string(base::UTF8ToUTF16(title)));
-}
-
-void remote_surface_set_top_inset(wl_client* client,
-                                  wl_resource* resource,
-                                  int32_t height) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetTopInset(height);
-}
-
-void remote_surface_activate(wl_client* client,
-                             wl_resource* resource,
-                             uint32_t serial) {
-  ShellSurfaceBase* shell_surface = GetUserDataAs<ShellSurfaceBase>(resource);
-  shell_surface->Activate();
-}
-
-void remote_surface_maximize(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetMaximized();
-}
-
-void remote_surface_minimize(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetMinimized();
-}
-
-void remote_surface_restore(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetRestored();
-}
-
-void remote_surface_fullscreen(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(true);
-}
-
-void remote_surface_unfullscreen(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(false);
-}
-
-void remote_surface_pin(wl_client* client,
-                        wl_resource* resource,
-                        int32_t trusted) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned(
-      trusted ? chromeos::WindowPinType::kTrustedPinned
-              : chromeos::WindowPinType::kPinned);
-}
-
-void remote_surface_unpin(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned(
-      chromeos::WindowPinType::kNone);
-}
-
-void remote_surface_set_system_modal(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(true);
-}
-
-void remote_surface_unset_system_modal(wl_client* client,
-                                       wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(false);
-}
-
-void remote_surface_set_rectangular_surface_shadow(wl_client* client,
-                                                   wl_resource* resource,
-                                                   int32_t x,
-                                                   int32_t y,
-                                                   int32_t width,
-                                                   int32_t height) {
-  // Shadow Bounds are set in pixels, and should not be scaled.
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  shell_surface->SetShadowBounds(gfx::Rect(x, y, width, height));
-}
-
-void remote_surface_set_systemui_visibility(wl_client* client,
-                                            wl_resource* resource,
-                                            uint32_t visibility) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemUiVisibility(
-      visibility != ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE);
-}
-
-void remote_surface_set_always_on_top(wl_client* client,
-                                      wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(true);
-}
-
-void remote_surface_unset_always_on_top(wl_client* client,
-                                        wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(false);
-}
-
-void remote_surface_ack_configure_DEPRECATED(wl_client* client,
-                                             wl_resource* resource,
-                                             uint32_t serial) {
-  NOTREACHED();
-}
-
-void remote_surface_move_DEPRECATED(wl_client* client, wl_resource* resource) {
-  NOTREACHED();
-}
-
-void remote_surface_set_window_type(wl_client* client,
-                                    wl_resource* resource,
-                                    uint32_t type) {
-  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
-  if (!widget)
-    return;
-
-  switch (type) {
-    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_NORMAL:
-      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, false);
-      break;
-    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_SYSTEM_UI:
-      // TODO(takise): Consider removing this as this window type was added for
-      // the old assistant and is not longer used.
-      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true);
-      wm::SetWindowVisibilityAnimationType(
-          widget->GetNativeWindow(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
-      break;
-    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_HIDDEN_IN_OVERVIEW:
-      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true);
-      break;
-  }
-}
-
-void remote_surface_resize_DEPRECATED(wl_client* client,
-                                      wl_resource* resource) {
-  // DEPRECATED
-  NOTREACHED();
-}
-
-void remote_surface_set_resize_outset_DEPRECATED(wl_client* client,
-                                                 wl_resource* resource,
-                                                 int32_t outset) {
-  // DEPRECATED
-  NOTREACHED();
-}
-
-void remote_surface_start_move(wl_client* client,
-                               wl_resource* resource,
-                               int32_t x,
-                               int32_t y) {
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  float scale = shell_surface->GetClientToDpScale();
-  gfx::PointF p(x, y);
-  shell_surface->StartDrag(HTCAPTION, gfx::ScalePoint(p, scale));
-}
-
-void remote_surface_set_can_maximize(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(true);
-}
-
-void remote_surface_unset_can_maximize(wl_client* client,
-                                       wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(false);
-}
-
-void remote_surface_set_min_size(wl_client* client,
-                                 wl_resource* resource,
-                                 int32_t width,
-                                 int32_t height) {
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  float scale = shell_surface->GetClientToDpScale();
-  gfx::Size s(width, height);
-  shell_surface->SetMinimumSize(gfx::ScaleToRoundedSize(s, scale));
-}
-
-void remote_surface_set_max_size(wl_client* client,
-                                 wl_resource* resource,
-                                 int32_t width,
-                                 int32_t height) {
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  float scale = shell_surface->GetClientToDpScale();
-  gfx::Size s(width, height);
-  shell_surface->SetMaximumSize(gfx::ScaleToRoundedSize(s, scale));
-}
-
-void remote_surface_set_aspect_ratio(wl_client* client,
-                                     wl_resource* resource,
-                                     int32_t aspect_ratio_width,
-                                     int32_t aspect_ratio_height) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAspectRatio(
-      gfx::SizeF(aspect_ratio_width, aspect_ratio_height));
-}
-
-void remote_surface_set_snapped_to_left(wl_client* client,
-                                        wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToLeft();
-}
-
-void remote_surface_set_snapped_to_right(wl_client* client,
-                                         wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToRight();
-}
-
-void remote_surface_start_resize(wl_client* client,
-                                 wl_resource* resource,
-                                 uint32_t direction,
-                                 int32_t x,
-                                 int32_t y) {
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  float scale = shell_surface->GetClientToDpScale();
-  gfx::PointF p(x, y);
-  shell_surface->StartDrag(Component(direction), gfx::ScalePoint(p, scale));
-}
-
-void remote_surface_set_frame(wl_client* client,
-                              wl_resource* resource,
-                              uint32_t type) {
-  ClientControlledShellSurface* shell_surface =
-      GetUserDataAs<ClientControlledShellSurface>(resource);
-  shell_surface->root_surface()->SetFrame(RemoteShellSurfaceFrameType(type));
-}
-
-void remote_surface_set_frame_buttons(wl_client* client,
-                                      wl_resource* resource,
-                                      uint32_t visible_button_mask,
-                                      uint32_t enabled_button_mask) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFrameButtons(
-      CaptionButtonMask(visible_button_mask),
-      CaptionButtonMask(enabled_button_mask));
-}
-
-void remote_surface_set_extra_title(wl_client* client,
-                                    wl_resource* resource,
-                                    const char* extra_title) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetExtraTitle(
-      std::u16string(base::UTF8ToUTF16(extra_title)));
-}
-
-ash::OrientationLockType OrientationLock(uint32_t orientation_lock) {
-  switch (orientation_lock) {
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_NONE:
-      return ash::OrientationLockType::kAny;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_CURRENT:
-      return ash::OrientationLockType::kCurrent;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT:
-      return ash::OrientationLockType::kPortrait;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE:
-      return ash::OrientationLockType::kLandscape;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_PRIMARY:
-      return ash::OrientationLockType::kPortraitPrimary;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_SECONDARY:
-      return ash::OrientationLockType::kPortraitSecondary;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_PRIMARY:
-      return ash::OrientationLockType::kLandscapePrimary;
-    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_SECONDARY:
-      return ash::OrientationLockType::kLandscapeSecondary;
-  }
-  VLOG(2) << "Unexpected value of orientation_lock: " << orientation_lock;
-  return ash::OrientationLockType::kAny;
-}
-
-void remote_surface_set_orientation_lock(wl_client* client,
-                                         wl_resource* resource,
-                                         uint32_t orientation_lock) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientationLock(
-      OrientationLock(orientation_lock));
-}
-
-void remote_surface_pip(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPip();
-}
-
-void remote_surface_set_bounds(wl_client* client,
-                               wl_resource* resource,
-                               uint32_t display_id_hi,
-                               uint32_t display_id_lo,
-                               int32_t x,
-                               int32_t y,
-                               int32_t width,
-                               int32_t height) {
-  // Bounds are set in pixels, and should not be scaled.
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds(
-      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo,
-      gfx::Rect(x, y, width, height));
-}
-
-void remote_surface_block_ime(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetImeBlocked(true);
-}
-
-void remote_surface_unblock_ime(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetImeBlocked(false);
-}
-
-void remote_surface_set_accessibility_id(wl_client* client,
-                                         wl_resource* resource,
-                                         int32_t accessibility_id) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)
-      ->SetClientAccessibilityId(accessibility_id);
-}
-
-void remote_surface_set_pip_original_window(wl_client* client,
-                                            wl_resource* resource) {
-  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
-  if (!widget) {
-    LOG(ERROR) << "no widget found for setting pip original window";
-    return;
-  }
-
-  widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, true);
-}
-
-void remote_surface_unset_pip_original_window(wl_client* client,
-                                              wl_resource* resource) {
-  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
-  if (!widget) {
-    LOG(ERROR) << "no widget found for unsetting pip original window";
-    return;
-  }
-
-  widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, false);
-}
-
-void remote_surface_set_system_gesture_exclusion(wl_client* client,
-                                                 wl_resource* resource,
-                                                 wl_resource* region_resource) {
-  auto* shell_surface = GetUserDataAs<ClientControlledShellSurface>(resource);
-  auto* widget = shell_surface->GetWidget();
-  if (!widget) {
-    LOG(ERROR) << "no widget found for setting system gesture exclusion";
-    return;
-  }
-
-  if (region_resource) {
-    SkRegion* dst = new SkRegion;
-    ScaleSkRegion(*GetUserDataAs<SkRegion>(region_resource),
-                  shell_surface->GetClientToDpScale(), dst);
-    widget->GetNativeWindow()->SetProperty(ash::kSystemGestureExclusionKey,
-                                           dst);
-  } else {
-    widget->GetNativeWindow()->ClearProperty(ash::kSystemGestureExclusionKey);
-  }
-}
-
-void remote_surface_set_resize_lock(wl_client* client, wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLock(true);
-}
-
-void remote_surface_unset_resize_lock(wl_client* client,
-                                      wl_resource* resource) {
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLock(false);
-}
-
-void remote_surface_set_bounds_in_output(wl_client* client,
-                                         wl_resource* resource,
-                                         wl_resource* output_resource,
-                                         int32_t x,
-                                         int32_t y,
-                                         int32_t width,
-                                         int32_t height) {
-  WaylandDisplayHandler* display_handler =
-      GetUserDataAs<WaylandDisplayHandler>(output_resource);
-  // Bounds are set in pixels, and should not be scaled.
-  GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds(
-      display_handler->id(), gfx::Rect(x, y, width, height));
-}
-
 const struct zcr_remote_surface_v1_interface remote_surface_implementation = {
-    remote_surface_destroy,
-    remote_surface_set_app_id,
-    remote_surface_set_window_geometry,
-    remote_surface_set_scale,
-    remote_surface_set_rectangular_shadow_DEPRECATED,
-    remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED,
-    remote_surface_set_title,
-    remote_surface_set_top_inset,
-    remote_surface_activate,
-    remote_surface_maximize,
-    remote_surface_minimize,
-    remote_surface_restore,
-    remote_surface_fullscreen,
-    remote_surface_unfullscreen,
-    remote_surface_pin,
-    remote_surface_unpin,
-    remote_surface_set_system_modal,
-    remote_surface_unset_system_modal,
-    remote_surface_set_rectangular_surface_shadow,
-    remote_surface_set_systemui_visibility,
-    remote_surface_set_always_on_top,
-    remote_surface_unset_always_on_top,
-    remote_surface_ack_configure_DEPRECATED,
-    remote_surface_move_DEPRECATED,
-    remote_surface_set_orientation,
-    remote_surface_set_window_type,
-    remote_surface_resize_DEPRECATED,
-    remote_surface_set_resize_outset_DEPRECATED,
-    remote_surface_start_move,
-    remote_surface_set_can_maximize,
-    remote_surface_unset_can_maximize,
-    remote_surface_set_min_size,
-    remote_surface_set_max_size,
-    remote_surface_set_snapped_to_left,
-    remote_surface_set_snapped_to_right,
-    remote_surface_start_resize,
-    remote_surface_set_frame,
-    remote_surface_set_frame_buttons,
-    remote_surface_set_extra_title,
-    remote_surface_set_orientation_lock,
-    remote_surface_pip,
-    remote_surface_set_bounds,
-    remote_surface_set_aspect_ratio,
-    remote_surface_block_ime,
-    remote_surface_unblock_ime,
-    remote_surface_set_accessibility_id,
-    remote_surface_set_pip_original_window,
-    remote_surface_unset_pip_original_window,
-    remote_surface_set_system_gesture_exclusion,
-    remote_surface_set_resize_lock,
-    remote_surface_unset_resize_lock,
-    remote_surface_set_bounds_in_output,
+    +[](wl_client* client, wl_resource* resource) {
+      wl_resource_destroy(resource);
+    },
+    zcr_remote_shell::remote_surface_set_app_id,
+    zcr_remote_shell::remote_surface_set_window_geometry,
+    zcr_remote_shell::remote_surface_set_scale,
+    zcr_remote_shell::remote_surface_set_rectangular_shadow_DEPRECATED,
+    zcr_remote_shell::
+        remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED,
+    zcr_remote_shell::remote_surface_set_title,
+    zcr_remote_shell::remote_surface_set_top_inset,
+    zcr_remote_shell::remote_surface_activate,
+    zcr_remote_shell::remote_surface_maximize,
+    zcr_remote_shell::remote_surface_minimize,
+    zcr_remote_shell::remote_surface_restore,
+    zcr_remote_shell::remote_surface_fullscreen,
+    zcr_remote_shell::remote_surface_unfullscreen,
+    zcr_remote_shell::remote_surface_pin,
+    zcr_remote_shell::remote_surface_unpin,
+    zcr_remote_shell::remote_surface_set_system_modal,
+    zcr_remote_shell::remote_surface_unset_system_modal,
+    zcr_remote_shell::remote_surface_set_rectangular_surface_shadow,
+    zcr_remote_shell::remote_surface_set_systemui_visibility,
+    zcr_remote_shell::remote_surface_set_always_on_top,
+    zcr_remote_shell::remote_surface_unset_always_on_top,
+    zcr_remote_shell::remote_surface_ack_configure_DEPRECATED,
+    zcr_remote_shell::remote_surface_move_DEPRECATED,
+    zcr_remote_shell::remote_surface_set_orientation,
+    zcr_remote_shell::remote_surface_set_window_type,
+    zcr_remote_shell::remote_surface_resize_DEPRECATED,
+    zcr_remote_shell::remote_surface_set_resize_outset_DEPRECATED,
+    zcr_remote_shell::remote_surface_start_move,
+    zcr_remote_shell::remote_surface_set_can_maximize,
+    zcr_remote_shell::remote_surface_unset_can_maximize,
+    zcr_remote_shell::remote_surface_set_min_size,
+    zcr_remote_shell::remote_surface_set_max_size,
+    zcr_remote_shell::remote_surface_set_snapped_to_left,
+    zcr_remote_shell::remote_surface_set_snapped_to_right,
+    zcr_remote_shell::remote_surface_start_resize,
+    zcr_remote_shell::remote_surface_set_frame,
+    zcr_remote_shell::remote_surface_set_frame_buttons,
+    zcr_remote_shell::remote_surface_set_extra_title,
+    zcr_remote_shell::remote_surface_set_orientation_lock,
+    zcr_remote_shell::remote_surface_pip,
+    zcr_remote_shell::remote_surface_set_bounds,
+    zcr_remote_shell::remote_surface_set_aspect_ratio,
+    zcr_remote_shell::remote_surface_block_ime,
+    zcr_remote_shell::remote_surface_unblock_ime,
+    zcr_remote_shell::remote_surface_set_accessibility_id,
+    zcr_remote_shell::remote_surface_set_pip_original_window,
+    zcr_remote_shell::remote_surface_unset_pip_original_window,
+    zcr_remote_shell::remote_surface_set_system_gesture_exclusion,
+    zcr_remote_shell::remote_surface_set_resize_lock,
+    zcr_remote_shell::remote_surface_unset_resize_lock,
+    zcr_remote_shell::remote_surface_set_bounds_in_output,
 };
 
-////////////////////////////////////////////////////////////////////////////////
-// notification_surface_interface:
-
-void notification_surface_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
-void notification_surface_set_app_id(wl_client* client,
-                                     wl_resource* resource,
-                                     const char* app_id) {
-  GetUserDataAs<NotificationSurface>(resource)->SetApplicationId(app_id);
-}
-
 const struct zcr_notification_surface_v1_interface
-    notification_surface_implementation = {notification_surface_destroy,
-                                           notification_surface_set_app_id};
-
-////////////////////////////////////////////////////////////////////////////////
-// input_method_surface_interface:
-
-void input_method_surface_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
-void input_method_surface_set_bounds(wl_client* client,
-                                     wl_resource* resource,
-                                     uint32_t display_id_hi,
-                                     uint32_t display_id_lo,
-                                     int32_t x,
-                                     int32_t y,
-                                     int32_t width,
-                                     int32_t height) {
-  GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
-      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo,
-      gfx::Rect(x, y, width, height));
-}
-
-void input_method_surface_set_bounds_in_output(wl_client* client,
-                                               wl_resource* resource,
-                                               wl_resource* output_resource,
-                                               int32_t x,
-                                               int32_t y,
-                                               int32_t width,
-                                               int32_t height) {
-  WaylandDisplayHandler* display_handler =
-      GetUserDataAs<WaylandDisplayHandler>(output_resource);
-  GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
-      display_handler->id(), gfx::Rect(x, y, width, height));
-}
+    notification_surface_implementation = {
+        +[](wl_client* client, wl_resource* resource) {
+          wl_resource_destroy(resource);
+        },
+        zcr_remote_shell::notification_surface_set_app_id,
+};
 
 const struct zcr_input_method_surface_v1_interface
     input_method_surface_implementation = {
-        input_method_surface_destroy,
-        input_method_surface_set_bounds,
-        input_method_surface_set_bounds_in_output,
+        +[](wl_client* client, wl_resource* resource) {
+          wl_resource_destroy(resource);
+        },
+        zcr_remote_shell::input_method_surface_set_bounds,
+        zcr_remote_shell::input_method_surface_set_bounds_in_output,
 };
 
-////////////////////////////////////////////////////////////////////////////////
-// toast_surface_interface:
-
-void toast_surface_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
-void toast_surface_set_position(wl_client* client,
-                                wl_resource* resource,
-                                uint32_t display_id_hi,
-                                uint32_t display_id_lo,
-                                int32_t x,
-                                int32_t y) {
-  GetUserDataAs<ToastSurface>(resource)->SetDisplay(
-      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo);
-  GetUserDataAs<ToastSurface>(resource)->SetBoundsOrigin(gfx::Point(x, y));
-}
-
-void toast_surface_set_size(wl_client* client,
-                            wl_resource* resource,
-                            int32_t width,
-                            int32_t height) {
-  GetUserDataAs<ToastSurface>(resource)->SetBoundsSize(
-      gfx::Size(width, height));
-}
-
-void toast_surface_set_bounds_in_output(wl_client* client,
-                                        wl_resource* resource,
-                                        wl_resource* output_resource,
-                                        int32_t x,
-                                        int32_t y,
-                                        int32_t width,
-                                        int32_t height) {
-  WaylandDisplayHandler* display_handler =
-      GetUserDataAs<WaylandDisplayHandler>(output_resource);
-  GetUserDataAs<ToastSurface>(resource)->SetBounds(
-      display_handler->id(), gfx::Rect(x, y, width, height));
-}
-
 const struct zcr_toast_surface_v1_interface toast_surface_implementation = {
-    toast_surface_destroy,
-    toast_surface_set_position,
-    toast_surface_set_size,
-    toast_surface_set_bounds_in_output,
+    +[](wl_client* client, wl_resource* resource) {
+      wl_resource_destroy(resource);
+    },
+    zcr_remote_shell::toast_surface_set_position,
+    zcr_remote_shell::toast_surface_set_size,
+    zcr_remote_shell::toast_surface_set_bounds_in_output,
 };
 
-////////////////////////////////////////////////////////////////////////////////
-// remote_output_interface:
-
-void remote_output_destroy(wl_client* client, wl_resource* resource) {
-  wl_resource_destroy(resource);
-}
-
 const struct zcr_remote_output_v1_interface remote_output_implementation = {
-    remote_output_destroy,
+    +[](wl_client* client, wl_resource* resource) {
+      wl_resource_destroy(resource);
+    },
 };
 
-class WaylandRemoteOutput : public WaylandDisplayObserver {
- public:
-  explicit WaylandRemoteOutput(wl_resource* resource) : resource_(resource) {}
-
-  // Overridden from WaylandDisplayObserver:
-  bool SendDisplayMetrics(const display::Display& display,
-                          uint32_t changed_metrics) override {
-    if (wl_resource_get_version(resource_) < 29)
-      return false;
-
-    if (initial_config_sent_ &&
-        !(changed_metrics &
-          display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) {
-      return false;
-    }
-
-    if (!initial_config_sent_) {
-      initial_config_sent_ = true;
-
-      uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32);
-      uint32_t display_id_lo = static_cast<uint32_t>(display.id());
-      zcr_remote_output_v1_send_display_id(resource_, display_id_hi,
-                                           display_id_lo);
-
-      constexpr int64_t DISPLAY_ID_PORT_MASK = 0xff;
-      uint32_t port =
-          static_cast<uint32_t>(display.id() & DISPLAY_ID_PORT_MASK);
-      zcr_remote_output_v1_send_port(resource_, port);
-
-      wl_array data;
-      wl_array_init(&data);
-
-      const auto& bytes =
-          WMHelper::GetInstance()->GetDisplayIdentificationData(display.id());
-      for (uint8_t byte : bytes) {
-        uint8_t* ptr =
-            static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t)));
-        DCHECK(ptr);
-        *ptr = byte;
-      }
-
-      zcr_remote_output_v1_send_identification_data(resource_, &data);
-      wl_array_release(&data);
-    }
-
-    float device_scale_factor = display.device_scale_factor();
-    gfx::Size size_in_pixel = display.GetSizeInPixel();
-
-    gfx::Insets insets_in_pixel = GetWorkAreaInsetsInPixel(
-        display, device_scale_factor, size_in_pixel, display.work_area());
-    zcr_remote_output_v1_send_insets(
-        resource_, insets_in_pixel.left(), insets_in_pixel.top(),
-        insets_in_pixel.right(), insets_in_pixel.bottom());
-
-    gfx::Insets stable_insets_in_pixel =
-        GetWorkAreaInsetsInPixel(display, device_scale_factor, size_in_pixel,
-                                 GetStableWorkArea(display));
-    zcr_remote_output_v1_send_stable_insets(
-        resource_, stable_insets_in_pixel.left(), stable_insets_in_pixel.top(),
-        stable_insets_in_pixel.right(), stable_insets_in_pixel.bottom());
-
-    // Currently no client uses zcr_remote_output_v1 systemui_visibility.
-    // Only systemui_behavior is sent here.
-    if (wl_resource_get_version(resource_) >=
-        ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_SINCE_VERSION) {
-      int systemui_behavior = SystemUiBehavior(display);
-      zcr_remote_output_v1_send_systemui_behavior(resource_, systemui_behavior);
-    }
-
-    return true;
-  }
-
- private:
-  wl_resource* const resource_;
-
-  bool initial_config_sent_ = false;
-
-  DISALLOW_COPY_AND_ASSIGN(WaylandRemoteOutput);
+const struct WaylandRemoteOutputEventMapping remote_output_event_mapping_v1 = {
+    zcr_remote_output_v1_send_identification_data,
+    zcr_remote_output_v1_send_display_id,
+    zcr_remote_output_v1_send_port,
+    zcr_remote_output_v1_send_insets,
+    zcr_remote_output_v1_send_stable_insets,
+    zcr_remote_output_v1_send_systemui_behavior,
+    ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_SINCE_VERSION,
+    ZCR_REMOTE_OUTPUT_V1_STABLE_INSETS_SINCE_VERSION,
 };
 
-////////////////////////////////////////////////////////////////////////////////
-// remote_shell_interface:
-
-// Implements remote shell interface and monitors workspace state needed
-// for the remote shell interface.
-class WaylandRemoteShell : public ash::TabletModeObserver,
-                           public display::DisplayObserver {
- public:
-  using OutputResourceProvider = base::RepeatingCallback<wl_resource*(int64_t)>;
-  WaylandRemoteShell(Display* display,
-                     wl_resource* remote_shell_resource,
-                     OutputResourceProvider output_provider)
-      : display_(display),
-        remote_shell_resource_(remote_shell_resource),
-        output_provider_(output_provider) {
-    WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
-    helper->AddTabletModeObserver(this);
-    helper->AddFrameThrottlingObserver();
-
-    layout_mode_ = helper->InTabletMode()
-                       ? ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET
-                       : ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
-    if (wl_resource_get_version(remote_shell_resource_) >=
-        ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_SINCE_VERSION) {
-      zcr_remote_shell_v1_send_layout_mode(remote_shell_resource_,
-                                           layout_mode_);
-    }
-
-    if (wl_resource_get_version(remote_shell_resource_) >= 8) {
-      double scale_factor = GetDefaultDeviceScaleFactor();
-      int32_t fixed_scale = To8_24Fixed(scale_factor);
-      zcr_remote_shell_v1_send_default_device_scale_factor(
-          remote_shell_resource_, fixed_scale);
-    }
-
-    SendDisplayMetrics();
-    display->seat()->SetFocusChangedCallback(
-        base::BindRepeating(&WaylandRemoteShell::FocusedSurfaceChanged,
-                            weak_ptr_factory_.GetWeakPtr()));
-  }
-  ~WaylandRemoteShell() override {
-    WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
-    helper->RemoveTabletModeObserver(this);
-    helper->RemoveFrameThrottlingObserver();
-  }
-
-  std::unique_ptr<ClientControlledShellSurface> CreateShellSurface(
-      Surface* surface,
-      int container,
-      double default_device_scale_factor) {
-    return display_->CreateOrGetClientControlledShellSurface(
-        surface, container, default_device_scale_factor,
-        use_default_scale_cancellation_);
-  }
-
-  std::unique_ptr<ClientControlledShellSurface::Delegate>
-  CreateShellSurfaceDelegate(wl_resource* resource) {
-    return std::make_unique<WaylandRemoteSurfaceDelegate>(
-        weak_ptr_factory_.GetWeakPtr(), resource);
-  }
-
-  std::unique_ptr<NotificationSurface> CreateNotificationSurface(
-      Surface* surface,
-      const std::string& notification_key) {
-    return display_->CreateNotificationSurface(surface, notification_key);
-  }
-
-  std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
-      Surface* surface,
-      double default_device_scale_factor) {
-    return display_->CreateInputMethodSurface(
-        surface, default_device_scale_factor, use_default_scale_cancellation_);
-  }
-
-  std::unique_ptr<ToastSurface> CreateToastSurface(
-      Surface* surface,
-      double default_device_scale_factor) {
-    return display_->CreateToastSurface(surface, default_device_scale_factor,
-                                        use_default_scale_cancellation_);
-  }
-
-  void SetUseDefaultScaleCancellation(bool use_default_scale) {
-    use_default_scale_cancellation_ = use_default_scale;
-    WMHelper::GetInstance()->SetDefaultScaleCancellation(use_default_scale);
-  }
-
-  void OnRemoteSurfaceDestroyed(wl_resource* resource) {
-    // Sometimes resource might be destroyed after bounds change is scheduled to
-    // |pending_bounds_change_| but before that bounds change is emitted. Erase
-    // it from |pending_bounds_changes_| to prevent crashes. See also
-    // https://crbug.com/1163271.
-    pending_bounds_changes_.erase(resource);
-  }
-
-  // Overridden from display::DisplayObserver:
-  void OnDisplayAdded(const display::Display& new_display) override {
-    ScheduleSendDisplayMetrics(0);
-  }
-
-  void OnDisplayRemoved(const display::Display& old_display) override {
-    ScheduleSendDisplayMetrics(0);
-  }
-
-  void OnDisplayMetricsChanged(const display::Display& display,
-                               uint32_t changed_metrics) override {
-    // No need to update when a primary display has changed without bounds
-    // change. See WaylandDisplayObserver::OnDisplayMetricsChanged
-    // for more details.
-    if (changed_metrics &
-        (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
-         DISPLAY_METRIC_ROTATION | DISPLAY_METRIC_WORK_AREA)) {
-      ScheduleSendDisplayMetrics(0);
-    }
-  }
-
-  // Overridden from ash::TabletModeObserver:
-  void OnTabletModeStarted() override {
-    layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET;
-    if (wl_resource_get_version(remote_shell_resource_) >=
-        ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_SINCE_VERSION)
-      zcr_remote_shell_v1_send_layout_mode(remote_shell_resource_,
-                                           layout_mode_);
-    ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
-  }
-  void OnTabletModeEnding() override {
-    layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
-    if (wl_resource_get_version(remote_shell_resource_) >=
-        ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_SINCE_VERSION)
-      zcr_remote_shell_v1_send_layout_mode(remote_shell_resource_,
-                                           layout_mode_);
-    ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
-  }
-  void OnTabletModeEnded() override {}
-
- private:
-  class WaylandRemoteSurfaceDelegate
-      : public ClientControlledShellSurface::Delegate {
-   public:
-    WaylandRemoteSurfaceDelegate(base::WeakPtr<WaylandRemoteShell> shell,
-                                 wl_resource* resource)
-        : shell_(std::move(shell)), resource_(resource) {}
-    ~WaylandRemoteSurfaceDelegate() override {
-      if (shell_)
-        shell_->OnRemoteSurfaceDestroyed(resource_);
-    }
-    WaylandRemoteSurfaceDelegate(const WaylandRemoteSurfaceDelegate&) = delete;
-    WaylandRemoteSurfaceDelegate& operator=(
-        const WaylandRemoteSurfaceDelegate&) = delete;
-
-   private:
-    // ClientControlledShellSurfaceDelegate:
-    void OnGeometryChanged(const gfx::Rect& geometry) override {
-      if (shell_)
-        shell_->OnRemoteSurfaceGeometryChanged(resource_, geometry);
-    }
-    void OnStateChanged(chromeos::WindowStateType old_state_type,
-                        chromeos::WindowStateType new_state_type) override {
-      shell_->OnRemoteSurfaceStateChanged(resource_, old_state_type,
-                                          new_state_type);
-    }
-    void OnBoundsChanged(chromeos::WindowStateType current_state,
-                         chromeos::WindowStateType requested_state,
-                         int64_t display_id,
-                         const gfx::Rect& bounds_in_display,
-                         bool is_resize,
-                         int bounds_change) override {
-      if (shell_) {
-        shell_->OnRemoteSurfaceBoundsChanged(
-            resource_, current_state, requested_state, display_id,
-            bounds_in_display, is_resize, bounds_change);
-      }
-    }
-    void OnDragStarted(int component) override {
-      zcr_remote_surface_v1_send_drag_started(resource_,
-                                              ResizeDirection(component));
-      wl_client_flush(wl_resource_get_client(resource_));
-    }
-    void OnDragFinished(int x, int y, bool canceled) override {
-      zcr_remote_surface_v1_send_drag_finished(resource_, x, y,
-                                               canceled ? 1 : 0);
-      wl_client_flush(wl_resource_get_client(resource_));
-    }
-    void OnZoomLevelChanged(ZoomChange zoom_change) override {
-      if (wl_resource_get_version(resource_) >= 23 && shell_)
-        shell_->OnRemoteSurfaceChangeZoomLevel(resource_, zoom_change);
-    }
-
-    base::WeakPtr<WaylandRemoteShell> shell_;
-    wl_resource* resource_;
-  };
-
-  void ScheduleSendDisplayMetrics(int delay_ms) {
-    needs_send_display_metrics_ = true;
-    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&WaylandRemoteShell::SendDisplayMetrics,
-                       weak_ptr_factory_.GetWeakPtr()),
-        base::TimeDelta::FromMilliseconds(delay_ms));
-  }
-
-  // Returns the transform that a display's output is currently adjusted for.
-  wl_output_transform DisplayTransform(display::Display::Rotation rotation) {
-    switch (rotation) {
-      case display::Display::ROTATE_0:
-        return WL_OUTPUT_TRANSFORM_NORMAL;
-      case display::Display::ROTATE_90:
-        return WL_OUTPUT_TRANSFORM_90;
-      case display::Display::ROTATE_180:
-        return WL_OUTPUT_TRANSFORM_180;
-      case display::Display::ROTATE_270:
-        return WL_OUTPUT_TRANSFORM_270;
-    }
-    NOTREACHED();
-    return WL_OUTPUT_TRANSFORM_NORMAL;
-  }
-
-  void SendDisplayMetrics() {
-    if (!needs_send_display_metrics_)
-      return;
-    needs_send_display_metrics_ = false;
-
-    const display::Screen* screen = display::Screen::GetScreen();
-    double default_dsf = GetDefaultDeviceScaleFactor();
-
-    for (const auto& display : screen->GetAllDisplays()) {
-      double device_scale_factor = display.device_scale_factor();
-
-      uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32);
-      uint32_t display_id_lo = static_cast<uint32_t>(display.id());
-      gfx::Size size_in_pixel = display.GetSizeInPixel();
-
-      wl_array data;
-      wl_array_init(&data);
-
-      const auto& bytes =
-          WMHelper::GetInstance()->GetDisplayIdentificationData(display.id());
-      for (uint8_t byte : bytes) {
-        uint8_t* ptr =
-            static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t)));
-        DCHECK(ptr);
-        *ptr = byte;
-      }
-
-      if (wl_resource_get_version(remote_shell_resource_) >= 20) {
-        // Apply the scale factor used on the remote shell client (ARC).
-        const gfx::Rect& bounds = display.bounds();
-
-        // Note: The origin is used just to identify the workspace on the client
-        // side, and does not account the actual pixel size of other workspace
-        // on the client side.
-        int x_px = base::ClampRound(bounds.x() * default_dsf);
-        int y_px = base::ClampRound(bounds.y() * default_dsf);
-
-        float server_to_client_pixel_scale = default_dsf / device_scale_factor;
-
-        gfx::Size size_in_client_pixel = gfx::ScaleToRoundedSize(
-            size_in_pixel, server_to_client_pixel_scale);
-
-        gfx::Insets insets_in_client_pixel = GetWorkAreaInsetsInPixel(
-            display, default_dsf, size_in_client_pixel, display.work_area());
-
-        gfx::Insets stable_insets_in_client_pixel =
-            GetWorkAreaInsetsInPixel(display, default_dsf, size_in_client_pixel,
-                                     GetStableWorkArea(display));
-
-        // TODO(b/148977363): Fix the issue and remove the hack.
-        MaybeApplyCTSHack(layout_mode_, size_in_pixel, &insets_in_client_pixel,
-                          &stable_insets_in_client_pixel);
-
-        int systemui_visibility = SystemUiVisibility(display);
-
-        zcr_remote_shell_v1_send_workspace_info(
-            remote_shell_resource_, display_id_hi, display_id_lo, x_px, y_px,
-            size_in_client_pixel.width(), size_in_client_pixel.height(),
-            insets_in_client_pixel.left(), insets_in_client_pixel.top(),
-            insets_in_client_pixel.right(), insets_in_client_pixel.bottom(),
-            stable_insets_in_client_pixel.left(),
-            stable_insets_in_client_pixel.top(),
-            stable_insets_in_client_pixel.right(),
-            stable_insets_in_client_pixel.bottom(), systemui_visibility,
-            DisplayTransform(display.rotation()), display.IsInternal(), &data);
-      } else {
-        NOTREACHED() << "The remote shell resource version being used ("
-                     << wl_resource_get_version(remote_shell_resource_)
-                     << ") is not supported.";
-      }
-
-      wl_array_release(&data);
-    }
-
-    zcr_remote_shell_v1_send_configure(remote_shell_resource_, layout_mode_);
-
-    base::flat_set<wl_client*> clients;
-    clients.insert(wl_resource_get_client(remote_shell_resource_));
-
-    for (const auto& bounds_change : pending_bounds_changes_) {
-      SendBoundsChanged(bounds_change.first, bounds_change.second.display_id,
-                        bounds_change.second.bounds_in_display,
-                        bounds_change.second.reason);
-      clients.insert(wl_resource_get_client(bounds_change.first));
-    }
-    pending_bounds_changes_.clear();
-
-    for (auto* client : clients)
-      wl_client_flush(client);
-  }
-
-  void FocusedSurfaceChanged(Surface* gained_active_surface,
-                             Surface* lost_active_surface,
-                             bool has_focused_client) {
-    if (gained_active_surface == lost_active_surface)
-      return;
-
-    wl_resource* gained_active_surface_resource =
-        gained_active_surface ? GetSurfaceResource(gained_active_surface)
-                              : nullptr;
-    wl_resource* lost_active_surface_resource =
-        lost_active_surface ? GetSurfaceResource(lost_active_surface) : nullptr;
-
-    wl_client* client = wl_resource_get_client(remote_shell_resource_);
-
-    // If surface that gained active is not owned by remote shell client then
-    // set it to null.
-    if (gained_active_surface_resource &&
-        wl_resource_get_client(gained_active_surface_resource) != client) {
-      gained_active_surface_resource = nullptr;
-    }
-
-    // If surface that lost active is not owned by remote shell client then
-    // set it to null.
-    if (lost_active_surface_resource &&
-        wl_resource_get_client(lost_active_surface_resource) != client) {
-      lost_active_surface_resource = nullptr;
-    }
-
-    if (wl_resource_get_version(remote_shell_resource_) >=
-        ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CHANGED_SINCE_VERSION) {
-      uint32_t focus_state;
-      if (gained_active_surface_resource) {
-        focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED;
-      } else if (has_focused_client) {
-        focus_state =
-            ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED;
-      } else {
-        focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS;
-      }
-      zcr_remote_shell_v1_send_desktop_focus_state_changed(
-          remote_shell_resource_, focus_state);
-    }
-
-    zcr_remote_shell_v1_send_activated(remote_shell_resource_,
-                                       gained_active_surface_resource,
-                                       lost_active_surface_resource);
-    wl_client_flush(client);
-  }
-
-  void OnRemoteSurfaceBoundsChanged(wl_resource* resource,
-                                    WindowStateType current_state,
-                                    WindowStateType requested_state,
-                                    int64_t display_id,
-                                    const gfx::Rect& bounds_in_display,
-                                    bool resize,
-                                    int bounds_change) {
-    zcr_remote_surface_v1_bounds_change_reason reason =
-        ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE;
-    if (!resize)
-      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE;
-    if (current_state == WindowStateType::kPip)
-      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP;
-    if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) {
-      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE;
-    } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
-      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE;
-    }
-    // Override the reason only if the window enters snapped mode. If the window
-    // resizes by dragging in snapped mode, we need to keep the original reason.
-    if (requested_state != current_state) {
-      if (requested_state == WindowStateType::kPrimarySnapped) {
-        reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT;
-      } else if (requested_state == WindowStateType::kSecondarySnapped) {
-        reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT;
-      }
-    }
-    if (wl_resource_get_version(resource) >= 22) {
-      if (needs_send_display_metrics_) {
-        pending_bounds_changes_.emplace(
-            std::make_pair<wl_resource*, BoundsChangeData>(
-                std::move(resource),
-                BoundsChangeData(display_id, bounds_in_display, reason)));
-        return;
-      }
-      SendBoundsChanged(resource, display_id, bounds_in_display, reason);
-    } else {
-      gfx::Rect bounds_in_screen = gfx::Rect(bounds_in_display);
-      display::Display display;
-      display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id,
-                                                            &display);
-      // The display ID should be valid.
-      DCHECK(display.is_valid());
-      if (display.is_valid())
-        bounds_in_screen.Offset(display.bounds().OffsetFromOrigin());
-      else
-        LOG(ERROR) << "Invalid Display in send_bounds_changed:" << display_id;
-
-      zcr_remote_surface_v1_send_bounds_changed(
-          resource, static_cast<uint32_t>(display_id >> 32),
-          static_cast<uint32_t>(display_id), bounds_in_screen.x(),
-          bounds_in_screen.y(), bounds_in_screen.width(),
-          bounds_in_screen.height(), reason);
-    }
-    wl_client_flush(wl_resource_get_client(resource));
-  }
-
-  void SendBoundsChanged(wl_resource* resource,
-                         int64_t display_id,
-                         const gfx::Rect& bounds_in_display,
-                         zcr_remote_surface_v1_bounds_change_reason reason) {
-    zcr_remote_surface_v1_send_bounds_changed(
-        resource, static_cast<uint32_t>(display_id >> 32),
-        static_cast<uint32_t>(display_id), bounds_in_display.x(),
-        bounds_in_display.y(), bounds_in_display.width(),
-        bounds_in_display.height(), reason);
-    if (wl_resource_get_version(resource) >=
-        ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED_IN_OUTPUT_SINCE_VERSION) {
-      wl_resource* output = output_provider_.Run(display_id);
-      if (output == nullptr) {
-        LOG(WARNING) << "Failed to get wayland_output resource for display_id: "
-                     << display_id;
-        return;
-      }
-      zcr_remote_surface_v1_send_bounds_changed_in_output(
-          resource, output, bounds_in_display.x(), bounds_in_display.y(),
-          bounds_in_display.width(), bounds_in_display.height(), reason);
-    }
-  }
-
-  void OnRemoteSurfaceStateChanged(wl_resource* resource,
-                                   WindowStateType old_state_type,
-                                   WindowStateType new_state_type) {
-    DCHECK_NE(old_state_type, new_state_type);
-    LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
-        << "Sending window state while there is a pending bounds change. This "
-           "should not happen.";
-
-    uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL;
-    switch (new_state_type) {
-      case WindowStateType::kMinimized:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED;
-        break;
-      case WindowStateType::kMaximized:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED;
-        break;
-      case WindowStateType::kFullscreen:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN;
-        break;
-      case WindowStateType::kPinned:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED;
-        break;
-      case WindowStateType::kTrustedPinned:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED;
-        break;
-      case WindowStateType::kPrimarySnapped:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED;
-        break;
-      case WindowStateType::kSecondarySnapped:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED;
-        break;
-      case WindowStateType::kPip:
-        state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP;
-        break;
-      default:
-        break;
-    }
-
-    zcr_remote_surface_v1_send_state_type_changed(resource, state_type);
-    wl_client_flush(wl_resource_get_client(resource));
-  }
-
-  void OnRemoteSurfaceChangeZoomLevel(wl_resource* resource,
-                                      ZoomChange change) {
-    int32_t value = 0;
-    switch (change) {
-      case ZoomChange::IN:
-        value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN;
-        break;
-      case ZoomChange::OUT:
-        value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT;
-        break;
-      case ZoomChange::RESET:
-        value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET;
-        break;
-    }
-    zcr_remote_surface_v1_send_change_zoom_level(resource, value);
-  }
-
-  void OnRemoteSurfaceGeometryChanged(wl_resource* resource,
-                                      const gfx::Rect& geometry) {
-    LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
-        << "Sending the new window geometry while there is a pending bounds "
-           "change. This should not happen.";
-    zcr_remote_surface_v1_send_window_geometry_changed(
-        resource, geometry.x(), geometry.y(), geometry.width(),
-        geometry.height());
-    wl_client_flush(wl_resource_get_client(resource));
-  }
-
-  struct BoundsChangeData {
-    int64_t display_id;
-    gfx::Rect bounds_in_display;
-    zcr_remote_surface_v1_bounds_change_reason reason;
-    BoundsChangeData(int64_t display_id,
-                     const gfx::Rect& bounds,
-                     zcr_remote_surface_v1_bounds_change_reason reason)
-        : display_id(display_id), bounds_in_display(bounds), reason(reason) {}
-  };
-
-  // The exo display instance. Not owned.
-  Display* const display_;
-
-  // The remote shell resource associated with observer.
-  wl_resource* const remote_shell_resource_;
-
-  // Callback to get the wl_output resource for a given display_id.
-  OutputResourceProvider const output_provider_;
-
-  // When true, the compositor should use the default_device_scale_factor to
-  // undo the scaling on the client buffers. When false, the compositor should
-  // use the device_scale_factor for the display for this scaling cancellation.
-  bool use_default_scale_cancellation_ = true;
-
-  bool needs_send_display_metrics_ = true;
-
-  int layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
-
-  base::flat_map<wl_resource*, BoundsChangeData> pending_bounds_changes_;
-
-  display::ScopedDisplayObserver display_observer_{this};
-
-  base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(WaylandRemoteShell);
+const WaylandRemoteShellEventMapping wayland_remote_shell_event_mapping_v1 = {
+    zcr_remote_surface_v1_send_window_geometry_changed,
+    zcr_remote_surface_v1_send_change_zoom_level,
+    zcr_remote_surface_v1_send_state_type_changed,
+    zcr_remote_surface_v1_send_bounds_changed_in_output,
+    zcr_remote_surface_v1_send_bounds_changed,
+    zcr_remote_shell_v1_send_activated,
+    zcr_remote_shell_v1_send_desktop_focus_state_changed,
+    zcr_remote_shell_v1_send_workspace_info,
+    zcr_remote_surface_v1_send_drag_finished,
+    zcr_remote_surface_v1_send_drag_started,
+    zcr_remote_shell_v1_send_layout_mode,
+    zcr_remote_shell_v1_send_default_device_scale_factor,
+    zcr_remote_shell_v1_send_configure,
+    ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED_IN_OUTPUT_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CHANGED_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V1_DEFAULT_DEVICE_SCALE_FACTOR_SINCE_VERSION,
+    ZCR_REMOTE_SURFACE_V1_CHANGE_ZOOM_LEVEL_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V1_WORKSPACE_INFO_SINCE_VERSION,
+    ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGED_IN_OUTPUT_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V1_SET_USE_DEFAULT_DEVICE_SCALE_CANCELLATION_SINCE_VERSION,
 };
 
-void remote_shell_destroy(wl_client* client, wl_resource* resource) {
-  // Nothing to do here.
-}
-
 int RemoteSurfaceContainer(uint32_t container) {
   switch (container) {
     case ZCR_REMOTE_SHELL_V1_CONTAINER_DEFAULT:
@@ -1497,9 +161,10 @@
                                      wl_resource* surface,
                                      uint32_t container) {
   WaylandRemoteShell* shell = GetUserDataAs<WaylandRemoteShell>(resource);
-  double default_scale_factor = wl_resource_get_version(resource) >= 8
-                                    ? GetDefaultDeviceScaleFactor()
-                                    : 1.0;
+  double default_scale_factor =
+      wl_resource_get_version(resource) >= 8
+          ? zcr_remote_shell::GetDefaultDeviceScaleFactor()
+          : 1.0;
 
   std::unique_ptr<ClientControlledShellSurface> shell_surface =
       shell->CreateShellSurface(GetUserDataAs<Surface>(surface),
@@ -1573,7 +238,8 @@
 
   std::unique_ptr<ClientControlledShellSurface> input_method_surface =
       GetUserDataAs<WaylandRemoteShell>(resource)->CreateInputMethodSurface(
-          GetUserDataAs<Surface>(surface), GetDefaultDeviceScaleFactor());
+          GetUserDataAs<Surface>(surface),
+          zcr_remote_shell::GetDefaultDeviceScaleFactor());
   if (!input_method_surface) {
     wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
                            "Cannot create an IME surface");
@@ -1600,7 +266,8 @@
 
   std::unique_ptr<ClientControlledShellSurface> toast_surface =
       GetUserDataAs<WaylandRemoteShell>(resource)->CreateToastSurface(
-          GetUserDataAs<Surface>(surface), GetDefaultDeviceScaleFactor());
+          GetUserDataAs<Surface>(surface),
+          zcr_remote_shell::GetDefaultDeviceScaleFactor());
   if (!toast_surface) {
     wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V1_ERROR_ROLE,
                            "Cannot create an toast surface");
@@ -1625,32 +292,24 @@
       wl_resource_create(client, &zcr_remote_output_v1_interface,
                          wl_resource_get_version(resource), id);
 
-  auto remote_output =
-      std::make_unique<WaylandRemoteOutput>(remote_output_resource);
+  auto remote_output = std::make_unique<WaylandRemoteOutput>(
+      remote_output_resource, remote_output_event_mapping_v1);
   display_handler->AddObserver(remote_output.get());
 
   SetImplementation(remote_output_resource, &remote_output_implementation,
                     std::move(remote_output));
 }
 
-void remote_shell_set_use_default_scale_cancellation(
-    wl_client*,
-    wl_resource* resource,
-    int32_t use_default_scale_cancellation) {
-  if (wl_resource_get_version(resource) < 29)
-    return;
-  GetUserDataAs<WaylandRemoteShell>(resource)->SetUseDefaultScaleCancellation(
-      use_default_scale_cancellation != 0);
-}
-
 const struct zcr_remote_shell_v1_interface remote_shell_implementation = {
-    remote_shell_destroy,
+    +[](wl_client* client, wl_resource* resource) {
+      // Nothing to do here.
+    },
     remote_shell_get_remote_surface,
     remote_shell_get_notification_surface,
     remote_shell_get_input_method_surface,
     remote_shell_get_toast_surface,
     remote_shell_get_remote_output,
-    remote_shell_set_use_default_scale_cancellation};
+    zcr_remote_shell::remote_shell_set_use_default_scale_cancellation};
 
 }  // namespace
 
@@ -1673,7 +332,9 @@
       resource, &remote_shell_implementation,
       std::make_unique<WaylandRemoteShell>(
           remote_shell_data->display, resource,
-          base::BindRepeating(remote_shell_data->output_provider, client)));
+          base::BindRepeating(remote_shell_data->output_provider, client),
+          wayland_remote_shell_event_mapping_v1,
+          /*use_default_scale_cancellation_default=*/true));
 }
 
 gfx::Insets GetWorkAreaInsetsInPixel(const display::Display& display,
@@ -1682,9 +343,10 @@
                                      const gfx::Rect& work_area_in_dp) {
   gfx::Rect local_work_area_in_dp = work_area_in_dp;
   local_work_area_in_dp.Offset(-display.bounds().x(), -display.bounds().y());
-  gfx::Rect work_area_in_pixel = ScaleBoundsToPixelSnappedToParent(
-      size_in_pixel, display.bounds().size(), device_scale_factor,
-      local_work_area_in_dp);
+  gfx::Rect work_area_in_pixel =
+      zcr_remote_shell::ScaleBoundsToPixelSnappedToParent(
+          size_in_pixel, display.bounds().size(), device_scale_factor,
+          local_work_area_in_dp);
   gfx::Insets insets_in_pixel =
       gfx::Rect(size_in_pixel).InsetsFrom(work_area_in_pixel);
 
diff --git a/components/exo/wayland/zcr_remote_shell.h b/components/exo/wayland/zcr_remote_shell.h
index 9ab8fc85..84f7540 100644
--- a/components/exo/wayland/zcr_remote_shell.h
+++ b/components/exo/wayland/zcr_remote_shell.h
@@ -20,7 +20,7 @@
 
 namespace display {
 class Display;
-}
+}  // namespace display
 
 namespace exo {
 
diff --git a/components/exo/wayland/zcr_remote_shell_event_mapping.h b/components/exo/wayland/zcr_remote_shell_event_mapping.h
new file mode 100644
index 0000000..f233a56d
--- /dev/null
+++ b/components/exo/wayland/zcr_remote_shell_event_mapping.h
@@ -0,0 +1,107 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_EVENT_MAPPING_H_
+#define COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_EVENT_MAPPING_H_
+
+#include <stdint.h>
+#include <wayland-server-core.h>
+#include <wayland-server-protocol-core.h>
+
+#include "base/callback.h"
+
+// These structs are populated with function pointers and values from the v1 and
+// v2 remote shell protocol.
+struct WaylandRemoteOutputEventMapping {
+  void (*send_identification_data)(struct wl_resource* resource_,
+                                   struct wl_array* identification_data);
+  void (*send_display_id)(struct wl_resource* resource_,
+                          uint32_t display_id_hi,
+                          uint32_t display_id_lo);
+  void (*send_port)(struct wl_resource* resource_, uint32_t port);
+  void (*send_insets)(struct wl_resource* resource_,
+                      int32_t inset_left,
+                      int32_t inset_top,
+                      int32_t inset_right,
+                      int32_t inset_bottom);
+  void (*send_stable_insets)(struct wl_resource* resource_,
+                             int32_t stable_inset_left,
+                             int32_t stable_inset_top,
+                             int32_t stable_inset_right,
+                             int32_t stable_inset_bottom);
+  void (*send_systemui_behavior)(struct wl_resource* resource_,
+                                 int32_t systemui_behavior);
+  int system_ui_behavior_since_version;
+  int stable_insets_since_version;
+};
+
+struct WaylandRemoteShellEventMapping {
+  void (*send_window_geometry_changed)(struct wl_resource* resource_,
+                                       int32_t x,
+                                       int32_t y,
+                                       int32_t width,
+                                       int32_t height);
+  void (*send_change_zoom_level)(struct wl_resource* resource_, int32_t change);
+  void (*send_state_type_changed)(struct wl_resource* resource_,
+                                  uint32_t state_type);
+  void (*send_bounds_changed_in_output)(struct wl_resource* resource_,
+                                        struct wl_resource* output,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height,
+                                        uint32_t bounds_change_reason);
+  void (*send_bounds_changed)(struct wl_resource* resource_,
+                              uint32_t display_id_hi,
+                              uint32_t display_id_lo,
+                              int32_t x,
+                              int32_t y,
+                              int32_t width,
+                              int32_t height,
+                              uint32_t bounds_change_reason);
+  void (*send_activated)(struct wl_resource* resource_,
+                         struct wl_resource* gained_active,
+                         struct wl_resource* lost_active);
+  void (*send_desktop_focus_state_changed)(struct wl_resource* resource_,
+                                           uint32_t focus_state);
+  void (*send_workspace_info)(struct wl_resource* resource_,
+                              uint32_t display_id_hi,
+                              uint32_t display_id_lo,
+                              int32_t x,
+                              int32_t y,
+                              int32_t width,
+                              int32_t height,
+                              int32_t inset_left,
+                              int32_t inset_top,
+                              int32_t inset_right,
+                              int32_t inset_bottom,
+                              int32_t stable_inset_left,
+                              int32_t stable_inset_top,
+                              int32_t stable_inset_right,
+                              int32_t stable_inset_bottom,
+                              int32_t systemui_visibility,
+                              int32_t transform,
+                              uint32_t is_internal,
+                              struct wl_array* identification_data);
+  void (*send_drag_finished)(struct wl_resource* resource_,
+                             int32_t x,
+                             int32_t y,
+                             int32_t canceled);
+  void (*send_drag_started)(struct wl_resource* resource_, uint32_t direction);
+  void (*send_layout_mode)(struct wl_resource* resource_, uint32_t layout_mode);
+  void (*send_default_device_scale_factor)(struct wl_resource* resource_,
+                                           int32_t scale);
+  void (*send_configure)(struct wl_resource* resource_, uint32_t layout_mode);
+
+  int bounds_changed_in_output_since_version;
+  int desktop_focus_state_changed_since_version;
+  int layout_mode_since_version;
+  int default_device_scale_factor_since_version;
+  int change_zoom_level_since_version;
+  int send_workspace_info_since_version;
+  int send_bounds_changed_since_version;
+  int set_use_default_scale_cancellation_since_version;
+};
+
+#endif  // COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_EVENT_MAPPNG_H_
diff --git a/components/exo/wayland/zcr_remote_shell_impl.cc b/components/exo/wayland/zcr_remote_shell_impl.cc
new file mode 100644
index 0000000..fc21b8f
--- /dev/null
+++ b/components/exo/wayland/zcr_remote_shell_impl.cc
@@ -0,0 +1,1515 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/exo/wayland/zcr_remote_shell_impl.h"
+
+#include "ash/shelf/shelf_layout_manager.h"
+#include "ash/shell.h"
+#include "ash/wm/window_resizer.h"
+#include "base/command_line.h"
+#include "chromeos/ui/base/window_pin_type.h"
+#include "components/exo/display.h"
+#include "components/exo/wayland/server_util.h"
+#include "components/exo/wm_helper_chromeos.h"
+#include "ui/display/screen.h"
+#include "ui/views/window/caption_button_types.h"
+#include "ui/wm/core/window_animations.h"
+
+namespace exo {
+namespace wayland {
+
+// Ensure that V1 and V2 constants remain identical.
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE) ==
+        static_cast<int>(
+            ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_VISIBLE),
+    "ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE and "
+    "ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_VISIBLE should be equal");
+static_assert(
+    static_cast<int>(
+        ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY) ==
+        static_cast<int>(
+            ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY),
+    "ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY and "
+    "ZCR_REMOTE_SURFACE_V2_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY "
+    "should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE) ==
+        static_cast<int>(ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_VISIBLE),
+    "ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE and "
+    "ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_VISIBLE should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN) ==
+        static_cast<int>(ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_HIDDEN),
+    "ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN and "
+    "ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_HIDDEN should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_NONE),
+              "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE and "
+              "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_NONE should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOP),
+              "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP and "
+              "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOP should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPRIGHT),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPRIGHT should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_RIGHT),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_RIGHT should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMRIGHT),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMRIGHT should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOM),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOM should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMLEFT),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_BOTTOMLEFT should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_LEFT),
+              "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT and "
+              "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_LEFT should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPLEFT),
+    "ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT and "
+    "ZCR_REMOTE_SURFACE_V2_RESIZE_DIRECTION_TOPLEFT should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET) ==
+                  static_cast<int>(ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_TABLET),
+              "ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET and "
+              "ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_TABLET should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED) ==
+                  static_cast<int>(ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_WINDOWED),
+              "ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED and "
+              "ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_WINDOWED should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED) ==
+        static_cast<int>(
+            ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED),
+    "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED and "
+    "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED should be equal");
+static_assert(
+    static_cast<int>(
+        ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED) ==
+        static_cast<int>(
+            ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED),
+    "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED and "
+    "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED should be "
+    "equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS) ==
+        static_cast<int>(ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_NO_FOCUS),
+    "ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS and "
+    "ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_NO_FOCUS should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_RESIZE),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_RESIZE should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_MOVE),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_MOVE should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_PIP),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_PIP should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE) ==
+        static_cast<int>(
+            ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_RESIZE),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_RESIZE should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_MOVE),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_DRAG_MOVE should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT) ==
+        static_cast<int>(
+            ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT should be equal");
+static_assert(
+    static_cast<int>(
+        ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT) ==
+        static_cast<int>(
+            ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT),
+    "ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT and "
+    "ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_NORMAL),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_NORMAL should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MINIMIZED),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MINIMIZED should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MAXIMIZED),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_MAXIMIZED should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_FULLSCREEN),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_FULLSCREEN should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PINNED),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PINNED should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_TRUSTED_PINNED),
+    "ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED and "
+    "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_TRUSTED_PINNED should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_LEFT_SNAPPED),
+    "ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED and "
+    "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_LEFT_SNAPPED should be equal");
+static_assert(
+    static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED) ==
+        static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_RIGHT_SNAPPED),
+    "ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED and "
+    "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_RIGHT_SNAPPED should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PIP),
+              "ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP and "
+              "ZCR_REMOTE_SURFACE_V2_STATE_TYPE_PIP should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_IN),
+              "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN and "
+              "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_IN should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_OUT),
+              "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT and "
+              "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_OUT should be equal");
+static_assert(static_cast<int>(ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET) ==
+                  static_cast<int>(ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_RESET),
+              "ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET and "
+              "ZCR_REMOTE_SURFACE_V2_ZOOM_CHANGE_RESET should be equal");
+
+using chromeos::WindowStateType;
+
+// We don't send configure immediately after tablet mode switch
+// because layout can change due to orientation lock state or accelerometer.
+constexpr int kConfigureDelayAfterLayoutSwitchMs = 300;
+
+// Convert to 8.24 fixed format.
+int32_t To8_24Fixed(double value) {
+  constexpr int kDecimalBits = 24;
+  return static_cast<int32_t>(value * (1 << kDecimalBits));
+}
+
+ash::ShelfLayoutManager* GetShelfLayoutManagerForDisplay(
+    const display::Display& display) {
+  auto* root = ash::Shell::GetRootWindowForDisplayId(display.id());
+  return ash::Shelf::ForWindow(root)->shelf_layout_manager();
+}
+
+int SystemUiVisibility(const display::Display& display) {
+  auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display);
+  switch (shelf_layout_manager->visibility_state()) {
+    case ash::SHELF_VISIBLE:
+      return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE;
+    case ash::SHELF_AUTO_HIDE:
+    case ash::SHELF_HIDDEN:
+      return ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_AUTOHIDE_NON_STICKY;
+  }
+  NOTREACHED() << "Got unexpected shelf visibility state "
+               << shelf_layout_manager->visibility_state();
+  return 0;
+}
+
+int SystemUiBehavior(const display::Display& display) {
+  auto* shelf_layout_manager = GetShelfLayoutManagerForDisplay(display);
+  switch (shelf_layout_manager->auto_hide_behavior()) {
+    case ash::ShelfAutoHideBehavior::kNever:
+      return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_VISIBLE;
+    case ash::ShelfAutoHideBehavior::kAlways:
+    case ash::ShelfAutoHideBehavior::kAlwaysHidden:
+      return ZCR_REMOTE_OUTPUT_V1_SYSTEMUI_BEHAVIOR_HIDDEN;
+  }
+  NOTREACHED() << "Got unexpected shelf visibility behavior.";
+  return 0;
+}
+
+uint32_t ResizeDirection(int component) {
+  switch (component) {
+    case HTCAPTION:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
+    case HTTOP:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP;
+    case HTTOPRIGHT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT;
+    case HTRIGHT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT;
+    case HTBOTTOMRIGHT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT;
+    case HTBOTTOM:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM;
+    case HTBOTTOMLEFT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT;
+    case HTLEFT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT;
+    case HTTOPLEFT:
+      return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT;
+    default:
+      LOG(ERROR) << "Unknown component:" << component;
+      break;
+  }
+  NOTREACHED();
+  return ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE;
+}
+
+// This is a workaround for b/148977363
+void MaybeApplyCTSHack(int layout_mode,
+                       const gfx::Size& size_in_pixel,
+                       gfx::Insets* insets_in_client_pixel,
+                       gfx::Insets* stable_insets_in_client_pixel) {
+  constexpr int kBadBottomInsets = 90;
+  if (layout_mode == ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET &&
+      size_in_pixel.width() == 3000 && size_in_pixel.height() == 2000 &&
+      stable_insets_in_client_pixel->bottom() == kBadBottomInsets) {
+    stable_insets_in_client_pixel->set_bottom(kBadBottomInsets + 1);
+    if (insets_in_client_pixel->bottom() == kBadBottomInsets)
+      insets_in_client_pixel->set_bottom(kBadBottomInsets + 1);
+  }
+}
+
+bool WaylandRemoteOutput::SendDisplayMetrics(const display::Display& display,
+                                             uint32_t changed_metrics) {
+  if (wl_resource_get_version(resource_) <
+      event_mapping_.stable_insets_since_version) {
+    return false;
+  }
+
+  if (initial_config_sent_ &&
+      !(changed_metrics & display::DisplayObserver::DISPLAY_METRIC_WORK_AREA)) {
+    return false;
+  }
+
+  if (!initial_config_sent_) {
+    initial_config_sent_ = true;
+
+    uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32);
+    uint32_t display_id_lo = static_cast<uint32_t>(display.id());
+    if (event_mapping_.send_display_id)
+      event_mapping_.send_display_id(resource_, display_id_hi, display_id_lo);
+
+    constexpr int64_t DISPLAY_ID_PORT_MASK = 0xff;
+    uint32_t port = static_cast<uint32_t>(display.id() & DISPLAY_ID_PORT_MASK);
+    if (event_mapping_.send_port)
+      event_mapping_.send_port(resource_, port);
+
+    wl_array data;
+    wl_array_init(&data);
+
+    const auto& bytes =
+        WMHelper::GetInstance()->GetDisplayIdentificationData(display.id());
+    for (uint8_t byte : bytes) {
+      uint8_t* ptr =
+          static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t)));
+      DCHECK(ptr);
+      *ptr = byte;
+    }
+    event_mapping_.send_identification_data(resource_, &data);
+    wl_array_release(&data);
+  }
+
+  float device_scale_factor = display.device_scale_factor();
+  gfx::Size size_in_pixel = display.GetSizeInPixel();
+
+  gfx::Insets insets_in_pixel = GetWorkAreaInsetsInPixel(
+      display, device_scale_factor, size_in_pixel, display.work_area());
+  event_mapping_.send_insets(resource_, insets_in_pixel.left(),
+                             insets_in_pixel.top(), insets_in_pixel.right(),
+                             insets_in_pixel.bottom());
+
+  gfx::Insets stable_insets_in_pixel = GetWorkAreaInsetsInPixel(
+      display, device_scale_factor, size_in_pixel, GetStableWorkArea(display));
+  event_mapping_.send_stable_insets(
+      resource_, stable_insets_in_pixel.left(), stable_insets_in_pixel.top(),
+      stable_insets_in_pixel.right(), stable_insets_in_pixel.bottom());
+
+  // Currently no client uses zcr_remote_output_v1 systemui_visibility.
+  // Only systemui_behavior is sent here.
+  if (wl_resource_get_version(resource_) >=
+      event_mapping_.system_ui_behavior_since_version) {
+    int systemui_behavior = SystemUiBehavior(display);
+    event_mapping_.send_systemui_behavior(resource_, systemui_behavior);
+  }
+
+  return true;
+}
+
+WaylandRemoteSurfaceDelegate::WaylandRemoteSurfaceDelegate(
+    base::WeakPtr<WaylandRemoteShell> shell,
+    wl_resource* resource,
+    WaylandRemoteShellEventMapping event_mapping)
+    : shell_(std::move(shell)),
+      resource_(resource),
+      event_mapping_(event_mapping) {}
+
+WaylandRemoteSurfaceDelegate::~WaylandRemoteSurfaceDelegate() {
+  if (shell_)
+    shell_->OnRemoteSurfaceDestroyed(resource_);
+}
+
+// ClientControlledShellSurfaceDelegate:
+void WaylandRemoteSurfaceDelegate::OnGeometryChanged(
+    const gfx::Rect& geometry) {
+  if (shell_)
+    shell_->OnRemoteSurfaceGeometryChanged(resource_, geometry);
+}
+void WaylandRemoteSurfaceDelegate::OnStateChanged(
+    chromeos::WindowStateType old_state_type,
+    chromeos::WindowStateType new_state_type) {
+  shell_->OnRemoteSurfaceStateChanged(resource_, old_state_type,
+                                      new_state_type);
+}
+void WaylandRemoteSurfaceDelegate::OnBoundsChanged(
+    chromeos::WindowStateType current_state,
+    chromeos::WindowStateType requested_state,
+    int64_t display_id,
+    const gfx::Rect& bounds_in_display,
+    bool is_resize,
+    int bounds_change) {
+  if (shell_) {
+    shell_->OnRemoteSurfaceBoundsChanged(
+        resource_, current_state, requested_state, display_id,
+        bounds_in_display, is_resize, bounds_change);
+  }
+}
+void WaylandRemoteSurfaceDelegate::OnDragStarted(int component) {
+  event_mapping_.send_drag_started(resource_, ResizeDirection(component));
+  wl_client_flush(wl_resource_get_client(resource_));
+}
+void WaylandRemoteSurfaceDelegate::OnDragFinished(int x, int y, bool canceled) {
+  event_mapping_.send_drag_finished(resource_, x, y, canceled ? 1 : 0);
+  wl_client_flush(wl_resource_get_client(resource_));
+}
+void WaylandRemoteSurfaceDelegate::OnZoomLevelChanged(ZoomChange zoom_change) {
+  if (wl_resource_get_version(resource_) >=
+          event_mapping_.change_zoom_level_since_version &&
+      shell_) {
+    shell_->OnRemoteSurfaceChangeZoomLevel(resource_, zoom_change);
+  }
+}
+
+using OutputResourceProvider = base::RepeatingCallback<wl_resource*(int64_t)>;
+
+WaylandRemoteShell::WaylandRemoteShell(
+    Display* display,
+    wl_resource* remote_shell_resource,
+    OutputResourceProvider output_provider,
+    WaylandRemoteShellEventMapping event_mapping,
+    bool use_default_scale_cancellation_default)
+    : event_mapping_(event_mapping),
+      display_(display),
+      remote_shell_resource_(remote_shell_resource),
+      output_provider_(output_provider),
+      use_default_scale_cancellation_(use_default_scale_cancellation_default) {
+  WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
+  helper->AddTabletModeObserver(this);
+  helper->AddFrameThrottlingObserver();
+
+  layout_mode_ = helper->InTabletMode()
+                     ? ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET
+                     : ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
+
+  if (wl_resource_get_version(remote_shell_resource_) >=
+      event_mapping_.layout_mode_since_version) {
+    event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_);
+  }
+
+  if (wl_resource_get_version(remote_shell_resource_) >=
+      event_mapping_.default_device_scale_factor_since_version) {
+    double scale_factor = GetDefaultDeviceScaleFactor();
+    int32_t fixed_scale = To8_24Fixed(scale_factor);
+    event_mapping_.send_default_device_scale_factor(remote_shell_resource_,
+                                                    fixed_scale);
+  }
+
+  SendDisplayMetrics();
+  // In v2 this event was moved to zaura shell
+  if (event_mapping_.send_activated) {
+    display->seat()->SetFocusChangedCallback(
+        base::BindRepeating(&WaylandRemoteShell::FocusedSurfaceChanged,
+                            weak_ptr_factory_.GetWeakPtr()));
+  }
+}
+
+WaylandRemoteShell::~WaylandRemoteShell() {
+  WMHelperChromeOS* helper = WMHelperChromeOS::GetInstance();
+  helper->RemoveTabletModeObserver(this);
+  helper->RemoveFrameThrottlingObserver();
+}
+
+std::unique_ptr<ClientControlledShellSurface>
+WaylandRemoteShell::CreateShellSurface(Surface* surface,
+                                       int container,
+                                       double default_device_scale_factor) {
+  return display_->CreateOrGetClientControlledShellSurface(
+      surface, container, default_device_scale_factor,
+      use_default_scale_cancellation_);
+}
+
+std::unique_ptr<ClientControlledShellSurface::Delegate>
+WaylandRemoteShell::CreateShellSurfaceDelegate(wl_resource* resource) {
+  return std::make_unique<WaylandRemoteSurfaceDelegate>(
+      weak_ptr_factory_.GetWeakPtr(), resource, event_mapping_);
+}
+
+std::unique_ptr<NotificationSurface>
+WaylandRemoteShell::CreateNotificationSurface(
+    Surface* surface,
+    const std::string& notification_key) {
+  return display_->CreateNotificationSurface(surface, notification_key);
+}
+
+std::unique_ptr<InputMethodSurface>
+WaylandRemoteShell::CreateInputMethodSurface(
+    Surface* surface,
+    double default_device_scale_factor) {
+  return display_->CreateInputMethodSurface(
+      surface, default_device_scale_factor, use_default_scale_cancellation_);
+}
+
+std::unique_ptr<ToastSurface> WaylandRemoteShell::CreateToastSurface(
+    Surface* surface,
+    double default_device_scale_factor) {
+  return display_->CreateToastSurface(surface, default_device_scale_factor,
+                                      use_default_scale_cancellation_);
+}
+
+void WaylandRemoteShell::SetUseDefaultScaleCancellation(
+    bool use_default_scale) {
+  use_default_scale_cancellation_ = use_default_scale;
+  WMHelper::GetInstance()->SetDefaultScaleCancellation(use_default_scale);
+}
+
+void WaylandRemoteShell::OnRemoteSurfaceDestroyed(wl_resource* resource) {
+  // Sometimes resource might be destroyed after bounds change is scheduled to
+  // |pending_bounds_change_| but before that bounds change is emitted. Erase
+  // it from |pending_bounds_changes_| to prevent crashes. See also
+  // https://crbug.com/1163271.
+  pending_bounds_changes_.erase(resource);
+}
+
+// Overridden from display::DisplayObserver:
+void WaylandRemoteShell::OnDisplayAdded(const display::Display& new_display) {
+  ScheduleSendDisplayMetrics(0);
+}
+
+void WaylandRemoteShell::OnDisplayRemoved(const display::Display& old_display) {
+  ScheduleSendDisplayMetrics(0);
+}
+
+void WaylandRemoteShell::OnDisplayMetricsChanged(
+    const display::Display& display,
+    uint32_t changed_metrics) {
+  // No need to update when a primary display has changed without bounds
+  // change. See WaylandDisplayObserver::OnDisplayMetricsChanged
+  // for more details.
+  if (changed_metrics &
+      (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_DEVICE_SCALE_FACTOR |
+       DISPLAY_METRIC_ROTATION | DISPLAY_METRIC_WORK_AREA)) {
+    ScheduleSendDisplayMetrics(0);
+  }
+}
+
+// Overridden from ash::TabletModeObserver:
+void WaylandRemoteShell::OnTabletModeStarted() {
+  layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_TABLET;
+  if (wl_resource_get_version(remote_shell_resource_) >=
+      event_mapping_.layout_mode_since_version)
+    event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_);
+  ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
+}
+void WaylandRemoteShell::OnTabletModeEnding() {
+  layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
+  if (wl_resource_get_version(remote_shell_resource_) >=
+      event_mapping_.layout_mode_since_version)
+    event_mapping_.send_layout_mode(remote_shell_resource_, layout_mode_);
+  ScheduleSendDisplayMetrics(kConfigureDelayAfterLayoutSwitchMs);
+}
+void WaylandRemoteShell::OnTabletModeEnded() {}
+
+void WaylandRemoteShell::ScheduleSendDisplayMetrics(int delay_ms) {
+  needs_send_display_metrics_ = true;
+  base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&WaylandRemoteShell::SendDisplayMetrics,
+                     weak_ptr_factory_.GetWeakPtr()),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+}
+
+// Returns the transform that a display's output is currently adjusted for.
+wl_output_transform WaylandRemoteShell::DisplayTransform(
+    display::Display::Rotation rotation) {
+  switch (rotation) {
+    case display::Display::ROTATE_0:
+      return WL_OUTPUT_TRANSFORM_NORMAL;
+    case display::Display::ROTATE_90:
+      return WL_OUTPUT_TRANSFORM_90;
+    case display::Display::ROTATE_180:
+      return WL_OUTPUT_TRANSFORM_180;
+    case display::Display::ROTATE_270:
+      return WL_OUTPUT_TRANSFORM_270;
+  }
+  NOTREACHED();
+  return WL_OUTPUT_TRANSFORM_NORMAL;
+}
+
+void WaylandRemoteShell::SendDisplayMetrics() {
+  if (!needs_send_display_metrics_)
+    return;
+  needs_send_display_metrics_ = false;
+
+  const display::Screen* screen = display::Screen::GetScreen();
+  double default_dsf = GetDefaultDeviceScaleFactor();
+
+  for (const auto& display : screen->GetAllDisplays()) {
+    double device_scale_factor = display.device_scale_factor();
+
+    uint32_t display_id_hi = static_cast<uint32_t>(display.id() >> 32);
+    uint32_t display_id_lo = static_cast<uint32_t>(display.id());
+    gfx::Size size_in_pixel = display.GetSizeInPixel();
+
+    wl_array data;
+    wl_array_init(&data);
+
+    const auto& bytes =
+        WMHelper::GetInstance()->GetDisplayIdentificationData(display.id());
+    for (uint8_t byte : bytes) {
+      uint8_t* ptr =
+          static_cast<uint8_t*>(wl_array_add(&data, sizeof(uint8_t)));
+      DCHECK(ptr);
+      *ptr = byte;
+    }
+
+    if (wl_resource_get_version(remote_shell_resource_) >=
+        event_mapping_.send_workspace_info_since_version) {
+      // Apply the scale factor used on the remote shell client (ARC).
+      const gfx::Rect& bounds = display.bounds();
+
+      // Note: The origin is used just to identify the workspace on the client
+      // side, and does not account the actual pixel size of other workspace
+      // on the client side.
+      int x_px = base::ClampRound(bounds.x() * default_dsf);
+      int y_px = base::ClampRound(bounds.y() * default_dsf);
+
+      float server_to_client_pixel_scale = default_dsf / device_scale_factor;
+
+      gfx::Size size_in_client_pixel =
+          gfx::ScaleToRoundedSize(size_in_pixel, server_to_client_pixel_scale);
+
+      gfx::Insets insets_in_client_pixel = GetWorkAreaInsetsInPixel(
+          display, default_dsf, size_in_client_pixel, display.work_area());
+
+      gfx::Insets stable_insets_in_client_pixel =
+          GetWorkAreaInsetsInPixel(display, default_dsf, size_in_client_pixel,
+                                   GetStableWorkArea(display));
+
+      // TODO(b/148977363): Fix the issue and remove the hack.
+      MaybeApplyCTSHack(layout_mode_, size_in_pixel, &insets_in_client_pixel,
+                        &stable_insets_in_client_pixel);
+
+      int systemui_visibility = SystemUiVisibility(display);
+      if (event_mapping_.send_workspace_info)
+        event_mapping_.send_workspace_info(
+            remote_shell_resource_, display_id_hi, display_id_lo, x_px, y_px,
+            size_in_client_pixel.width(), size_in_client_pixel.height(),
+            insets_in_client_pixel.left(), insets_in_client_pixel.top(),
+            insets_in_client_pixel.right(), insets_in_client_pixel.bottom(),
+            stable_insets_in_client_pixel.left(),
+            stable_insets_in_client_pixel.top(),
+            stable_insets_in_client_pixel.right(),
+            stable_insets_in_client_pixel.bottom(), systemui_visibility,
+            DisplayTransform(display.rotation()), display.IsInternal(), &data);
+    } else {
+      NOTREACHED() << "The remote shell resource version being used ("
+                   << wl_resource_get_version(remote_shell_resource_)
+                   << ") is not supported.";
+    }
+
+    wl_array_release(&data);
+  }
+  if (event_mapping_.send_configure)
+    event_mapping_.send_configure(remote_shell_resource_, layout_mode_);
+
+  base::flat_set<wl_client*> clients;
+  clients.insert(wl_resource_get_client(remote_shell_resource_));
+
+  for (const auto& bounds_change : pending_bounds_changes_) {
+    SendBoundsChanged(bounds_change.first, bounds_change.second.display_id,
+                      bounds_change.second.bounds_in_display,
+                      bounds_change.second.reason);
+    clients.insert(wl_resource_get_client(bounds_change.first));
+  }
+  pending_bounds_changes_.clear();
+
+  for (auto* client : clients)
+    wl_client_flush(client);
+}
+
+void WaylandRemoteShell::FocusedSurfaceChanged(Surface* gained_active_surface,
+                                               Surface* lost_active_surface,
+                                               bool has_focused_client) {
+  if (gained_active_surface == lost_active_surface)
+    return;
+
+  wl_resource* gained_active_surface_resource =
+      gained_active_surface ? GetSurfaceResource(gained_active_surface)
+                            : nullptr;
+  wl_resource* lost_active_surface_resource =
+      lost_active_surface ? GetSurfaceResource(lost_active_surface) : nullptr;
+
+  wl_client* client = wl_resource_get_client(remote_shell_resource_);
+
+  // If surface that gained active is not owned by remote shell client then
+  // set it to null.
+  if (gained_active_surface_resource &&
+      wl_resource_get_client(gained_active_surface_resource) != client) {
+    gained_active_surface_resource = nullptr;
+  }
+
+  // If surface that lost active is not owned by remote shell client then
+  // set it to null.
+  if (lost_active_surface_resource &&
+      wl_resource_get_client(lost_active_surface_resource) != client) {
+    lost_active_surface_resource = nullptr;
+  }
+
+  if (wl_resource_get_version(remote_shell_resource_) >=
+      event_mapping_.desktop_focus_state_changed_since_version) {
+    uint32_t focus_state;
+    if (gained_active_surface_resource) {
+      focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_CLIENT_FOCUSED;
+    } else if (has_focused_client) {
+      focus_state =
+          ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_OTHER_CLIENT_FOCUSED;
+    } else {
+      focus_state = ZCR_REMOTE_SHELL_V1_DESKTOP_FOCUS_STATE_NO_FOCUS;
+    }
+    event_mapping_.send_desktop_focus_state_changed(remote_shell_resource_,
+                                                    focus_state);
+  }
+
+  if (event_mapping_.send_activated) {
+    event_mapping_.send_activated(remote_shell_resource_,
+                                  gained_active_surface_resource,
+                                  lost_active_surface_resource);
+  }
+
+  wl_client_flush(client);
+}
+
+void WaylandRemoteShell::OnRemoteSurfaceBoundsChanged(
+    wl_resource* resource,
+    WindowStateType current_state,
+    WindowStateType requested_state,
+    int64_t display_id,
+    const gfx::Rect& bounds_in_display,
+    bool resize,
+    int bounds_change) {
+  zcr_remote_surface_v1_bounds_change_reason reason =
+      ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_RESIZE;
+  if (!resize)
+    reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_MOVE;
+  if (current_state == WindowStateType::kPip)
+    reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_PIP;
+  if (bounds_change & ash::WindowResizer::kBoundsChange_Resizes) {
+    reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_RESIZE;
+  } else if (bounds_change & ash::WindowResizer::kBoundsChange_Repositions) {
+    reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_DRAG_MOVE;
+  }
+  // Override the reason only if the window enters snapped mode. If the window
+  // resizes by dragging in snapped mode, we need to keep the original reason.
+  if (requested_state != current_state) {
+    if (requested_state == WindowStateType::kPrimarySnapped) {
+      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_LEFT;
+    } else if (requested_state == WindowStateType::kSecondarySnapped) {
+      reason = ZCR_REMOTE_SURFACE_V1_BOUNDS_CHANGE_REASON_SNAP_TO_RIGHT;
+    }
+  }
+
+  if (wl_resource_get_version(resource) >=
+      event_mapping_.send_bounds_changed_since_version) {
+    if (needs_send_display_metrics_) {
+      pending_bounds_changes_.emplace(
+          std::make_pair<wl_resource*, BoundsChangeData>(
+              std::move(resource),
+              BoundsChangeData(display_id, bounds_in_display, reason)));
+      return;
+    }
+    SendBoundsChanged(resource, display_id, bounds_in_display, reason);
+  } else {
+    gfx::Rect bounds_in_screen = gfx::Rect(bounds_in_display);
+    display::Display display;
+    display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id, &display);
+    // The display ID should be valid.
+    DCHECK(display.is_valid());
+    if (display.is_valid())
+      bounds_in_screen.Offset(display.bounds().OffsetFromOrigin());
+    else
+      LOG(ERROR) << "Invalid Display in send_bounds_changed:" << display_id;
+
+    event_mapping_.send_bounds_changed(
+        resource, static_cast<uint32_t>(display_id >> 32),
+        static_cast<uint32_t>(display_id), bounds_in_screen.x(),
+        bounds_in_screen.y(), bounds_in_screen.width(),
+        bounds_in_screen.height(), reason);
+  }
+  wl_client_flush(wl_resource_get_client(resource));
+}
+
+void WaylandRemoteShell::SendBoundsChanged(
+    wl_resource* resource,
+    int64_t display_id,
+    const gfx::Rect& bounds_in_display,
+    zcr_remote_surface_v1_bounds_change_reason reason) {
+  if (event_mapping_.send_bounds_changed)
+    event_mapping_.send_bounds_changed(
+        resource, static_cast<uint32_t>(display_id >> 32),
+        static_cast<uint32_t>(display_id), bounds_in_display.x(),
+        bounds_in_display.y(), bounds_in_display.width(),
+        bounds_in_display.height(), reason);
+
+  if (wl_resource_get_version(resource) >=
+      event_mapping_.bounds_changed_in_output_since_version) {
+    wl_resource* output = output_provider_.Run(display_id);
+    if (output == nullptr) {
+      LOG(WARNING) << "Failed to get wayland_output resource for display_id: "
+                   << display_id;
+      return;
+    }
+    event_mapping_.send_bounds_changed_in_output(
+        resource, output, bounds_in_display.x(), bounds_in_display.y(),
+        bounds_in_display.width(), bounds_in_display.height(), reason);
+  }
+}
+
+void WaylandRemoteShell::OnRemoteSurfaceStateChanged(
+    wl_resource* resource,
+    WindowStateType old_state_type,
+    WindowStateType new_state_type) {
+  DCHECK_NE(old_state_type, new_state_type);
+  LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
+      << "Sending window state while there is a pending bounds change. This "
+         "should not happen.";
+
+  uint32_t state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_NORMAL;
+  switch (new_state_type) {
+    case WindowStateType::kMinimized:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MINIMIZED;
+      break;
+    case WindowStateType::kMaximized:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_MAXIMIZED;
+      break;
+    case WindowStateType::kFullscreen:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_FULLSCREEN;
+      break;
+    case WindowStateType::kPinned:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PINNED;
+      break;
+    case WindowStateType::kTrustedPinned:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_TRUSTED_PINNED;
+      break;
+    case WindowStateType::kPrimarySnapped:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_LEFT_SNAPPED;
+      break;
+    case WindowStateType::kSecondarySnapped:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_RIGHT_SNAPPED;
+      break;
+    case WindowStateType::kPip:
+      state_type = ZCR_REMOTE_SHELL_V1_STATE_TYPE_PIP;
+      break;
+    default:
+      break;
+  }
+
+  event_mapping_.send_state_type_changed(resource, state_type);
+  wl_client_flush(wl_resource_get_client(resource));
+}
+
+void WaylandRemoteShell::OnRemoteSurfaceChangeZoomLevel(wl_resource* resource,
+                                                        ZoomChange change) {
+  int32_t value = 0;
+  switch (change) {
+    case ZoomChange::IN:
+      value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_IN;
+      break;
+    case ZoomChange::OUT:
+      value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_OUT;
+      break;
+    case ZoomChange::RESET:
+      value = ZCR_REMOTE_SURFACE_V1_ZOOM_CHANGE_RESET;
+      break;
+  }
+  event_mapping_.send_change_zoom_level(resource, value);
+  wl_client_flush(wl_resource_get_client(resource));
+}
+
+void WaylandRemoteShell::OnRemoteSurfaceGeometryChanged(
+    wl_resource* resource,
+    const gfx::Rect& geometry) {
+  LOG_IF(ERROR, pending_bounds_changes_.count(resource) > 0)
+      << "Sending the new window geometry while there is a pending bounds "
+         "change. This should not happen.";
+  event_mapping_.send_window_geometry_changed(resource, geometry.x(),
+                                              geometry.y(), geometry.width(),
+                                              geometry.height());
+  wl_client_flush(wl_resource_get_client(resource));
+}
+
+namespace switches {
+
+// This flag can be used to emulate device scale factor for remote shell.
+constexpr char kForceRemoteShellScale[] = "force-remote-shell-scale";
+
+}  // namespace switches
+
+using chromeos::WindowStateType;
+
+namespace zcr_remote_shell {
+
+// Returns the scale factor to be used by remote shell clients.
+double GetDefaultDeviceScaleFactor() {
+  // A flag used by VM to emulate a device scale for a particular board.
+  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+  if (command_line->HasSwitch(switches::kForceRemoteShellScale)) {
+    std::string value =
+        command_line->GetSwitchValueASCII(switches::kForceRemoteShellScale);
+    double scale = 1.0;
+    if (base::StringToDouble(value, &scale))
+      return std::max(1.0, scale);
+  }
+  return WMHelper::GetInstance()->GetDefaultDeviceScaleFactor();
+}
+
+// Scale the |child_bounds| in such a way that if it should fill the
+// |parent_size|'s width/height, it returns the |parent_size_in_pixel|'s
+// width/height.
+gfx::Rect ScaleBoundsToPixelSnappedToParent(
+    const gfx::Size& parent_size_in_pixel,
+    const gfx::Size& parent_size,
+    float device_scale_factor,
+    const gfx::Rect& child_bounds) {
+  int right = child_bounds.right();
+  int bottom = child_bounds.bottom();
+
+  int new_x = base::ClampRound(child_bounds.x() * device_scale_factor);
+  int new_y = base::ClampRound(child_bounds.y() * device_scale_factor);
+
+  int new_right = right == parent_size.width()
+                      ? parent_size_in_pixel.width()
+                      : base::ClampRound(right * device_scale_factor);
+
+  int new_bottom = bottom == parent_size.height()
+                       ? parent_size_in_pixel.height()
+                       : base::ClampRound(bottom * device_scale_factor);
+  return gfx::Rect(new_x, new_y, new_right - new_x, new_bottom - new_y);
+}
+
+void ScaleSkRegion(const SkRegion& src, float scale, SkRegion* dst) {
+  SkRegion::Iterator iter(src);
+  for (; !iter.done(); iter.next()) {
+    SkIRect r;
+    r.fLeft = base::ClampFloor(iter.rect().fLeft * scale);
+    r.fTop = base::ClampFloor(iter.rect().fTop * scale);
+    r.fRight = base::ClampCeil(iter.rect().fRight * scale);
+    r.fBottom = base::ClampCeil(iter.rect().fBottom * scale);
+    dst->op(r, SkRegion::kUnion_Op);
+  }
+}
+
+int Component(uint32_t direction) {
+  switch (direction) {
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_NONE:
+      return HTNOWHERE;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOP:
+      return HTTOP;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPRIGHT:
+      return HTTOPRIGHT;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_RIGHT:
+      return HTRIGHT;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMRIGHT:
+      return HTBOTTOMRIGHT;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOM:
+      return HTBOTTOM;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_BOTTOMLEFT:
+      return HTBOTTOMLEFT;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_LEFT:
+      return HTLEFT;
+    case ZCR_REMOTE_SURFACE_V1_RESIZE_DIRECTION_TOPLEFT:
+      return HTTOPLEFT;
+    default:
+      VLOG(2) << "Unknown direction:" << direction;
+      break;
+  }
+  return HTNOWHERE;
+}
+
+uint32_t CaptionButtonMask(uint32_t mask) {
+  uint32_t caption_button_icon_mask = 0;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_BACK)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_BACK;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MENU)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MENU;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MINIMIZE)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_MINIMIZE;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_MAXIMIZE_RESTORE)
+    caption_button_icon_mask |= 1
+                                << views::CAPTION_BUTTON_ICON_MAXIMIZE_RESTORE;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CLOSE)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CLOSE;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_ZOOM)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_ZOOM;
+  if (mask & ZCR_REMOTE_SURFACE_V1_FRAME_BUTTON_TYPE_CENTER)
+    caption_button_icon_mask |= 1 << views::CAPTION_BUTTON_ICON_CENTER;
+  return caption_button_icon_mask;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// remote_surface_interface:
+
+SurfaceFrameType RemoteShellSurfaceFrameType(uint32_t frame_type) {
+  switch (frame_type) {
+    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NONE:
+      return SurfaceFrameType::NONE;
+    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_NORMAL:
+      return SurfaceFrameType::NORMAL;
+    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_SHADOW:
+      return SurfaceFrameType::SHADOW;
+    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_AUTOHIDE:
+      return SurfaceFrameType::AUTOHIDE;
+    case ZCR_REMOTE_SURFACE_V1_FRAME_TYPE_OVERLAY:
+      return SurfaceFrameType::OVERLAY;
+    default:
+      VLOG(2) << "Unknown remote-shell frame type: " << frame_type;
+      return SurfaceFrameType::NONE;
+  }
+}
+
+void remote_surface_set_app_id(wl_client* client,
+                               wl_resource* resource,
+                               const char* app_id) {
+  GetUserDataAs<ShellSurfaceBase>(resource)->SetApplicationId(app_id);
+}
+
+void remote_surface_set_window_geometry(wl_client* client,
+                                        wl_resource* resource,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height) {
+  // DEPRECATED - Use set_bounds to send bounds info with a display_id.
+  GetUserDataAs<ShellSurfaceBase>(resource)->SetGeometry(
+      gfx::Rect(x, y, width, height));
+}
+
+void remote_surface_set_orientation(wl_client* client,
+                                    wl_resource* resource,
+                                    int32_t orientation) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientation(
+      orientation == ZCR_REMOTE_SURFACE_V1_ORIENTATION_PORTRAIT
+          ? Orientation::PORTRAIT
+          : Orientation::LANDSCAPE);
+}
+
+void remote_surface_set_scale(wl_client* client,
+                              wl_resource* resource,
+                              wl_fixed_t scale) {
+  // DEPRECATED (b/141715728) - The server updates the client's scale.
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetScale(
+      wl_fixed_to_double(scale));
+}
+
+void remote_surface_set_rectangular_shadow_DEPRECATED(wl_client* client,
+                                                      wl_resource* resource,
+                                                      int32_t x,
+                                                      int32_t y,
+                                                      int32_t width,
+                                                      int32_t height) {
+  NOTREACHED();
+}
+
+void remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED(
+    wl_client* client,
+    wl_resource* resource,
+    wl_fixed_t opacity) {
+  NOTREACHED();
+}
+
+void remote_surface_set_title(wl_client* client,
+                              wl_resource* resource,
+                              const char* title) {
+  GetUserDataAs<ShellSurfaceBase>(resource)->SetTitle(
+      std::u16string(base::UTF8ToUTF16(title)));
+}
+
+void remote_surface_set_top_inset(wl_client* client,
+                                  wl_resource* resource,
+                                  int32_t height) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetTopInset(height);
+}
+
+void remote_surface_activate(wl_client* client,
+                             wl_resource* resource,
+                             uint32_t serial) {
+  ShellSurfaceBase* shell_surface = GetUserDataAs<ShellSurfaceBase>(resource);
+  shell_surface->Activate();
+}
+
+void remote_surface_maximize(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetMaximized();
+}
+
+void remote_surface_minimize(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetMinimized();
+}
+
+void remote_surface_restore(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetRestored();
+}
+
+void remote_surface_fullscreen(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(true);
+}
+
+void remote_surface_unfullscreen(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFullscreen(false);
+}
+
+void remote_surface_pin(wl_client* client,
+                        wl_resource* resource,
+                        int32_t trusted) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned(
+      trusted ? chromeos::WindowPinType::kTrustedPinned
+              : chromeos::WindowPinType::kPinned);
+}
+
+void remote_surface_unpin(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPinned(
+      chromeos::WindowPinType::kNone);
+}
+
+void remote_surface_set_system_modal(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(true);
+}
+
+void remote_surface_unset_system_modal(wl_client* client,
+                                       wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemModal(false);
+}
+
+void remote_surface_set_rectangular_surface_shadow(wl_client* client,
+                                                   wl_resource* resource,
+                                                   int32_t x,
+                                                   int32_t y,
+                                                   int32_t width,
+                                                   int32_t height) {
+  // Shadow Bounds are set in pixels, and should not be scaled.
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  shell_surface->SetShadowBounds(gfx::Rect(x, y, width, height));
+}
+
+void remote_surface_set_systemui_visibility(wl_client* client,
+                                            wl_resource* resource,
+                                            uint32_t visibility) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSystemUiVisibility(
+      visibility != ZCR_REMOTE_SURFACE_V1_SYSTEMUI_VISIBILITY_STATE_VISIBLE);
+}
+
+void remote_surface_set_always_on_top(wl_client* client,
+                                      wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(true);
+}
+
+void remote_surface_unset_always_on_top(wl_client* client,
+                                        wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAlwaysOnTop(false);
+}
+
+void remote_surface_ack_configure_DEPRECATED(wl_client* client,
+                                             wl_resource* resource,
+                                             uint32_t serial) {
+  NOTREACHED();
+}
+
+void remote_surface_move_DEPRECATED(wl_client* client, wl_resource* resource) {
+  NOTREACHED();
+}
+
+void remote_surface_set_window_type(wl_client* client,
+                                    wl_resource* resource,
+                                    uint32_t type) {
+  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
+  if (!widget)
+    return;
+
+  switch (type) {
+    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_NORMAL:
+      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, false);
+      break;
+    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_SYSTEM_UI:
+      // TODO(takise): Consider removing this as this window type was added for
+      // the old assistant and is not longer used.
+      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true);
+      wm::SetWindowVisibilityAnimationType(
+          widget->GetNativeWindow(), wm::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE);
+      break;
+    case ZCR_REMOTE_SURFACE_V1_WINDOW_TYPE_HIDDEN_IN_OVERVIEW:
+      widget->GetNativeWindow()->SetProperty(ash::kHideInOverviewKey, true);
+      break;
+  }
+}
+
+void remote_surface_resize_DEPRECATED(wl_client* client,
+                                      wl_resource* resource) {
+  // DEPRECATED
+  NOTREACHED();
+}
+
+void remote_surface_set_resize_outset_DEPRECATED(wl_client* client,
+                                                 wl_resource* resource,
+                                                 int32_t outset) {
+  // DEPRECATED
+  NOTREACHED();
+}
+
+void remote_surface_start_move(wl_client* client,
+                               wl_resource* resource,
+                               int32_t x,
+                               int32_t y) {
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  float scale = shell_surface->GetClientToDpScale();
+  gfx::PointF p(x, y);
+  shell_surface->StartDrag(HTCAPTION, gfx::ScalePoint(p, scale));
+}
+
+void remote_surface_set_can_maximize(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(true);
+}
+
+void remote_surface_unset_can_maximize(wl_client* client,
+                                       wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetCanMaximize(false);
+}
+
+void remote_surface_set_min_size(wl_client* client,
+                                 wl_resource* resource,
+                                 int32_t width,
+                                 int32_t height) {
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  float scale = shell_surface->GetClientToDpScale();
+  gfx::Size s(width, height);
+  shell_surface->SetMinimumSize(gfx::ScaleToRoundedSize(s, scale));
+}
+
+void remote_surface_set_max_size(wl_client* client,
+                                 wl_resource* resource,
+                                 int32_t width,
+                                 int32_t height) {
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  float scale = shell_surface->GetClientToDpScale();
+  gfx::Size s(width, height);
+  shell_surface->SetMaximumSize(gfx::ScaleToRoundedSize(s, scale));
+}
+
+void remote_surface_set_aspect_ratio(wl_client* client,
+                                     wl_resource* resource,
+                                     int32_t aspect_ratio_width,
+                                     int32_t aspect_ratio_height) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetAspectRatio(
+      gfx::SizeF(aspect_ratio_width, aspect_ratio_height));
+}
+
+void remote_surface_set_snapped_to_left(wl_client* client,
+                                        wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToLeft();
+}
+
+void remote_surface_set_snapped_to_right(wl_client* client,
+                                         wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetSnappedToRight();
+}
+
+void remote_surface_start_resize(wl_client* client,
+                                 wl_resource* resource,
+                                 uint32_t direction,
+                                 int32_t x,
+                                 int32_t y) {
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  float scale = shell_surface->GetClientToDpScale();
+  gfx::PointF p(x, y);
+  shell_surface->StartDrag(Component(direction), gfx::ScalePoint(p, scale));
+}
+
+void remote_surface_set_frame(wl_client* client,
+                              wl_resource* resource,
+                              uint32_t type) {
+  ClientControlledShellSurface* shell_surface =
+      GetUserDataAs<ClientControlledShellSurface>(resource);
+  shell_surface->root_surface()->SetFrame(RemoteShellSurfaceFrameType(type));
+}
+
+void remote_surface_set_frame_buttons(wl_client* client,
+                                      wl_resource* resource,
+                                      uint32_t visible_button_mask,
+                                      uint32_t enabled_button_mask) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetFrameButtons(
+      CaptionButtonMask(visible_button_mask),
+      CaptionButtonMask(enabled_button_mask));
+}
+
+void remote_surface_set_extra_title(wl_client* client,
+                                    wl_resource* resource,
+                                    const char* extra_title) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetExtraTitle(
+      std::u16string(base::UTF8ToUTF16(extra_title)));
+}
+
+ash::OrientationLockType OrientationLock(uint32_t orientation_lock) {
+  switch (orientation_lock) {
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_NONE:
+      return ash::OrientationLockType::kAny;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_CURRENT:
+      return ash::OrientationLockType::kCurrent;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT:
+      return ash::OrientationLockType::kPortrait;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE:
+      return ash::OrientationLockType::kLandscape;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_PRIMARY:
+      return ash::OrientationLockType::kPortraitPrimary;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_PORTRAIT_SECONDARY:
+      return ash::OrientationLockType::kPortraitSecondary;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_PRIMARY:
+      return ash::OrientationLockType::kLandscapePrimary;
+    case ZCR_REMOTE_SURFACE_V1_ORIENTATION_LOCK_LANDSCAPE_SECONDARY:
+      return ash::OrientationLockType::kLandscapeSecondary;
+  }
+  VLOG(2) << "Unexpected value of orientation_lock: " << orientation_lock;
+  return ash::OrientationLockType::kAny;
+}
+
+void remote_surface_set_orientation_lock(wl_client* client,
+                                         wl_resource* resource,
+                                         uint32_t orientation_lock) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetOrientationLock(
+      OrientationLock(orientation_lock));
+}
+
+void remote_surface_pip(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetPip();
+}
+
+void remote_surface_set_bounds(wl_client* client,
+                               wl_resource* resource,
+                               uint32_t display_id_hi,
+                               uint32_t display_id_lo,
+                               int32_t x,
+                               int32_t y,
+                               int32_t width,
+                               int32_t height) {
+  // Bounds are set in pixels, and should not be scaled.
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds(
+      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo,
+      gfx::Rect(x, y, width, height));
+}
+
+void remote_surface_block_ime(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetImeBlocked(true);
+}
+
+void remote_surface_unblock_ime(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetImeBlocked(false);
+}
+
+void remote_surface_set_accessibility_id(wl_client* client,
+                                         wl_resource* resource,
+                                         int32_t accessibility_id) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)
+      ->SetClientAccessibilityId(accessibility_id);
+}
+
+void remote_surface_set_pip_original_window(wl_client* client,
+                                            wl_resource* resource) {
+  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
+  if (!widget) {
+    LOG(ERROR) << "no widget found for setting pip original window";
+    return;
+  }
+
+  widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, true);
+}
+
+void remote_surface_unset_pip_original_window(wl_client* client,
+                                              wl_resource* resource) {
+  auto* widget = GetUserDataAs<ShellSurfaceBase>(resource)->GetWidget();
+  if (!widget) {
+    LOG(ERROR) << "no widget found for unsetting pip original window";
+    return;
+  }
+
+  widget->GetNativeWindow()->SetProperty(ash::kPipOriginalWindowKey, false);
+}
+
+void remote_surface_set_system_gesture_exclusion(wl_client* client,
+                                                 wl_resource* resource,
+                                                 wl_resource* region_resource) {
+  auto* shell_surface = GetUserDataAs<ClientControlledShellSurface>(resource);
+  auto* widget = shell_surface->GetWidget();
+  if (!widget) {
+    LOG(ERROR) << "no widget found for setting system gesture exclusion";
+    return;
+  }
+
+  if (region_resource) {
+    SkRegion* dst = new SkRegion;
+    ScaleSkRegion(*GetUserDataAs<SkRegion>(region_resource),
+                  shell_surface->GetClientToDpScale(), dst);
+    widget->GetNativeWindow()->SetProperty(ash::kSystemGestureExclusionKey,
+                                           dst);
+  } else {
+    widget->GetNativeWindow()->ClearProperty(ash::kSystemGestureExclusionKey);
+  }
+}
+
+void remote_surface_set_resize_lock(wl_client* client, wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLock(true);
+}
+
+void remote_surface_unset_resize_lock(wl_client* client,
+                                      wl_resource* resource) {
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetResizeLock(false);
+}
+
+void remote_surface_set_bounds_in_output(wl_client* client,
+                                         wl_resource* resource,
+                                         wl_resource* output_resource,
+                                         int32_t x,
+                                         int32_t y,
+                                         int32_t width,
+                                         int32_t height) {
+  WaylandDisplayHandler* display_handler =
+      GetUserDataAs<WaylandDisplayHandler>(output_resource);
+  // Bounds are set in pixels, and should not be scaled.
+  GetUserDataAs<ClientControlledShellSurface>(resource)->SetBounds(
+      display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// notification_surface_interface:
+
+void notification_surface_set_app_id(wl_client* client,
+                                     wl_resource* resource,
+                                     const char* app_id) {
+  GetUserDataAs<NotificationSurface>(resource)->SetApplicationId(app_id);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// input_method_surface_interface:
+
+void input_method_surface_set_bounds(wl_client* client,
+                                     wl_resource* resource,
+                                     uint32_t display_id_hi,
+                                     uint32_t display_id_lo,
+                                     int32_t x,
+                                     int32_t y,
+                                     int32_t width,
+                                     int32_t height) {
+  GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
+      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo,
+      gfx::Rect(x, y, width, height));
+}
+
+void input_method_surface_set_bounds_in_output(wl_client* client,
+                                               wl_resource* resource,
+                                               wl_resource* output_resource,
+                                               int32_t x,
+                                               int32_t y,
+                                               int32_t width,
+                                               int32_t height) {
+  WaylandDisplayHandler* display_handler =
+      GetUserDataAs<WaylandDisplayHandler>(output_resource);
+  GetUserDataAs<InputMethodSurface>(resource)->SetBounds(
+      display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// toast_surface_interface:
+
+void toast_surface_set_position(wl_client* client,
+                                wl_resource* resource,
+                                uint32_t display_id_hi,
+                                uint32_t display_id_lo,
+                                int32_t x,
+                                int32_t y) {
+  GetUserDataAs<ToastSurface>(resource)->SetDisplay(
+      static_cast<int64_t>(display_id_hi) << 32 | display_id_lo);
+  GetUserDataAs<ToastSurface>(resource)->SetBoundsOrigin(gfx::Point(x, y));
+}
+
+void toast_surface_set_size(wl_client* client,
+                            wl_resource* resource,
+                            int32_t width,
+                            int32_t height) {
+  GetUserDataAs<ToastSurface>(resource)->SetBoundsSize(
+      gfx::Size(width, height));
+}
+
+void toast_surface_set_bounds_in_output(wl_client* client,
+                                        wl_resource* resource,
+                                        wl_resource* output_resource,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height) {
+  WaylandDisplayHandler* display_handler =
+      GetUserDataAs<WaylandDisplayHandler>(output_resource);
+  GetUserDataAs<ToastSurface>(resource)->SetBounds(
+      display_handler->id(), gfx::Rect(x, y, width, height));
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// remote_shell_interface:
+
+void remote_shell_set_use_default_scale_cancellation(
+    wl_client*,
+    wl_resource* resource,
+    int32_t use_default_scale_cancellation) {
+  auto* shell = GetUserDataAs<WaylandRemoteShell>(resource);
+  if (wl_resource_get_version(resource) <
+      shell->event_mapping_.set_use_default_scale_cancellation_since_version) {
+    return;
+  }
+  shell->SetUseDefaultScaleCancellation(use_default_scale_cancellation != 0);
+}
+
+}  // namespace zcr_remote_shell
+
+}  // namespace wayland
+}  // namespace exo
diff --git a/components/exo/wayland/zcr_remote_shell_impl.h b/components/exo/wayland/zcr_remote_shell_impl.h
new file mode 100644
index 0000000..d532f21
--- /dev/null
+++ b/components/exo/wayland/zcr_remote_shell_impl.h
@@ -0,0 +1,451 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_IMPL_H_
+#define COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_IMPL_H_
+
+#include <remote-shell-unstable-v1-server-protocol.h>
+#include <remote-shell-unstable-v2-server-protocol.h>
+
+#include "ash/wm/window_state.h"
+#include "components/exo/client_controlled_shell_surface.h"
+#include "components/exo/input_method_surface.h"
+#include "components/exo/notification_surface.h"
+#include "components/exo/surface.h"
+#include "components/exo/toast_surface.h"
+#include "components/exo/wayland/wayland_display_observer.h"
+#include "components/exo/wayland/zcr_remote_shell.h"
+#include "components/exo/wayland/zcr_remote_shell_event_mapping.h"
+
+namespace exo {
+namespace wayland {
+
+using chromeos::WindowStateType;
+
+class WaylandRemoteOutput : public WaylandDisplayObserver {
+ public:
+  WaylandRemoteOutput(wl_resource* resource,
+                      WaylandRemoteOutputEventMapping event_mapping)
+      : resource_(resource), event_mapping_(event_mapping) {}
+  WaylandRemoteOutput(const WaylandRemoteOutput&) = delete;
+  WaylandRemoteOutput& operator=(const WaylandRemoteOutput&) = delete;
+
+  // Overridden from WaylandDisplayObserver:
+  bool SendDisplayMetrics(const display::Display& display,
+                          uint32_t changed_metrics) override;
+
+ private:
+  wl_resource* const resource_;
+
+  bool initial_config_sent_ = false;
+
+  WaylandRemoteOutputEventMapping const event_mapping_;
+};
+
+// Implements remote shell interface and monitors workspace state needed
+// for the remote shell interface.
+class WaylandRemoteShell : public ash::TabletModeObserver,
+                           public display::DisplayObserver {
+ public:
+  using OutputResourceProvider = base::RepeatingCallback<wl_resource*(int64_t)>;
+
+  WaylandRemoteShell(Display* display,
+                     wl_resource* remote_shell_resource,
+                     OutputResourceProvider output_provider,
+                     WaylandRemoteShellEventMapping event_mapping,
+                     bool use_default_scale_cancellation_default);
+
+  WaylandRemoteShell(const WaylandRemoteShell&) = delete;
+
+  WaylandRemoteShell& operator=(const WaylandRemoteShell&) = delete;
+
+  ~WaylandRemoteShell() override;
+
+  std::unique_ptr<ClientControlledShellSurface> CreateShellSurface(
+      Surface* surface,
+      int container,
+      double default_device_scale_factor);
+
+  std::unique_ptr<ClientControlledShellSurface::Delegate>
+  CreateShellSurfaceDelegate(wl_resource* resource);
+  std::unique_ptr<NotificationSurface> CreateNotificationSurface(
+      Surface* surface,
+      const std::string& notification_key);
+
+  std::unique_ptr<InputMethodSurface> CreateInputMethodSurface(
+      Surface* surface,
+      double default_device_scale_factor);
+
+  std::unique_ptr<ToastSurface> CreateToastSurface(
+      Surface* surface,
+      double default_device_scale_factor);
+
+  void SetUseDefaultScaleCancellation(bool use_default_scale);
+
+  void OnRemoteSurfaceDestroyed(wl_resource* resource);
+  // Overridden from display::DisplayObserver:
+  void OnDisplayAdded(const display::Display& new_display) override;
+  void OnDisplayRemoved(const display::Display& old_display) override;
+
+  void OnDisplayMetricsChanged(const display::Display& display,
+                               uint32_t changed_metrics) override;
+
+  // Overridden from ash::TabletModeObserver:
+  void OnTabletModeStarted() override;
+  void OnTabletModeEnding() override;
+  void OnTabletModeEnded() override;
+
+  WaylandRemoteShellEventMapping const event_mapping_;
+
+ private:
+  void ScheduleSendDisplayMetrics(int delay_ms);
+
+  // Returns the transform that a display's output is currently adjusted for.
+  wl_output_transform DisplayTransform(display::Display::Rotation rotation);
+
+  void SendDisplayMetrics();
+
+  void FocusedSurfaceChanged(Surface* gained_active_surface,
+                             Surface* lost_active_surface,
+                             bool has_focused_client);
+
+  void OnRemoteSurfaceBoundsChanged(wl_resource* resource,
+                                    WindowStateType current_state,
+                                    WindowStateType requested_state,
+                                    int64_t display_id,
+                                    const gfx::Rect& bounds_in_display,
+                                    bool resize,
+                                    int bounds_change);
+
+  void SendBoundsChanged(wl_resource* resource,
+                         int64_t display_id,
+                         const gfx::Rect& bounds_in_display,
+                         zcr_remote_surface_v1_bounds_change_reason reason);
+
+  void OnRemoteSurfaceStateChanged(wl_resource* resource,
+                                   WindowStateType old_state_type,
+                                   WindowStateType new_state_type);
+
+  void OnRemoteSurfaceChangeZoomLevel(wl_resource* resource, ZoomChange change);
+
+  void OnRemoteSurfaceGeometryChanged(wl_resource* resource,
+                                      const gfx::Rect& geometry);
+  struct BoundsChangeData {
+    int64_t display_id;
+    gfx::Rect bounds_in_display;
+    zcr_remote_surface_v1_bounds_change_reason reason;
+    BoundsChangeData(int64_t display_id,
+                     const gfx::Rect& bounds,
+                     zcr_remote_surface_v1_bounds_change_reason reason)
+        : display_id(display_id), bounds_in_display(bounds), reason(reason) {}
+  };
+
+  // The exo display instance. Not owned.
+  Display* const display_;
+
+  // The remote shell resource associated with observer.
+  wl_resource* const remote_shell_resource_;
+
+  // Callback to get the wl_output resource for a given display_id.
+  OutputResourceProvider const output_provider_;
+
+  // When true, the compositor should use the default_device_scale_factor to
+  // undo the scaling on the client buffers. When false, the compositor should
+  // use the device_scale_factor for the display for this scaling cancellation.
+  // in v2 this is always false.
+  bool use_default_scale_cancellation_;
+
+  bool needs_send_display_metrics_ = true;
+
+  int layout_mode_ = ZCR_REMOTE_SHELL_V1_LAYOUT_MODE_WINDOWED;
+
+  base::flat_map<wl_resource*, BoundsChangeData> pending_bounds_changes_;
+
+  display::ScopedDisplayObserver display_observer_{this};
+
+  base::WeakPtrFactory<WaylandRemoteShell> weak_ptr_factory_{this};
+
+  friend class WaylandRemoteSurfaceDelegate;
+};
+
+class WaylandRemoteSurfaceDelegate
+    : public ClientControlledShellSurface::Delegate {
+ public:
+  WaylandRemoteSurfaceDelegate(base::WeakPtr<WaylandRemoteShell> shell,
+                               wl_resource* resource,
+                               WaylandRemoteShellEventMapping event_mapping);
+  ~WaylandRemoteSurfaceDelegate() override;
+  WaylandRemoteSurfaceDelegate(const WaylandRemoteSurfaceDelegate&) = delete;
+  WaylandRemoteSurfaceDelegate& operator=(const WaylandRemoteSurfaceDelegate&) =
+      delete;
+
+ private:
+  // ClientControlledShellSurfaceDelegate:
+  void OnGeometryChanged(const gfx::Rect& geometry) override;
+  void OnStateChanged(chromeos::WindowStateType old_state_type,
+                      chromeos::WindowStateType new_state_type) override;
+  void OnBoundsChanged(chromeos::WindowStateType current_state,
+                       chromeos::WindowStateType requested_state,
+                       int64_t display_id,
+                       const gfx::Rect& bounds_in_display,
+                       bool is_resize,
+                       int bounds_change) override;
+  void OnDragStarted(int component) override;
+  void OnDragFinished(int x, int y, bool canceled) override;
+  void OnZoomLevelChanged(ZoomChange zoom_change) override;
+
+  base::WeakPtr<WaylandRemoteShell> shell_;
+  wl_resource* resource_;
+  WaylandRemoteShellEventMapping const event_mapping_;
+};
+
+namespace zcr_remote_shell {
+
+double GetDefaultDeviceScaleFactor();
+
+gfx::Rect ScaleBoundsToPixelSnappedToParent(
+    const gfx::Size& parent_size_in_pixel,
+    const gfx::Size& parent_size,
+    float device_scale_factor,
+    const gfx::Rect& child_bounds);
+
+void remote_surface_destroy(wl_client* client, wl_resource* resource);
+void remote_surface_set_app_id(wl_client* client,
+                               wl_resource* resource,
+                               const char* app_id);
+void remote_surface_set_window_geometry(wl_client* client,
+                                        wl_resource* resource,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height);
+void remote_surface_set_orientation(wl_client* client,
+                                    wl_resource* resource,
+                                    int32_t orientation);
+
+void remote_surface_set_title(wl_client* client,
+                              wl_resource* resource,
+                              const char* title);
+void remote_surface_set_top_inset(wl_client* client,
+                                  wl_resource* resource,
+                                  int32_t height);
+
+void remote_surface_maximize(wl_client* client, wl_resource* resource);
+void remote_surface_minimize(wl_client* client, wl_resource* resource);
+void remote_surface_restore(wl_client* client, wl_resource* resource);
+
+void remote_surface_fullscreen(wl_client* client, wl_resource* resource);
+
+void remote_surface_pin(wl_client* client,
+                        wl_resource* resource,
+                        int32_t trusted);
+
+void remote_surface_unpin(wl_client* client, wl_resource* resource);
+void remote_surface_set_system_modal(wl_client* client, wl_resource* resource);
+
+void remote_surface_unset_system_modal(wl_client* client,
+                                       wl_resource* resource);
+
+void remote_surface_set_rectangular_surface_shadow(wl_client* client,
+                                                   wl_resource* resource,
+                                                   int32_t x,
+                                                   int32_t y,
+                                                   int32_t width,
+                                                   int32_t height);
+void remote_surface_set_systemui_visibility(wl_client* client,
+                                            wl_resource* resource,
+                                            uint32_t visibility);
+void remote_surface_set_always_on_top(wl_client* client, wl_resource* resource);
+void remote_surface_unset_always_on_top(wl_client* client,
+                                        wl_resource* resource);
+
+void remote_surface_start_move(wl_client* client,
+                               wl_resource* resource,
+                               int32_t x,
+                               int32_t y);
+void remote_surface_set_can_maximize(wl_client* client, wl_resource* resource);
+void remote_surface_unset_can_maximize(wl_client* client,
+                                       wl_resource* resource);
+void remote_surface_set_min_size(wl_client* client,
+                                 wl_resource* resource,
+                                 int32_t width,
+                                 int32_t height);
+void remote_surface_set_max_size(wl_client* client,
+                                 wl_resource* resource,
+                                 int32_t width,
+                                 int32_t height);
+void remote_surface_set_aspect_ratio(wl_client* client,
+                                     wl_resource* resource,
+                                     int32_t aspect_ratio_width,
+                                     int32_t aspect_ratio_height);
+void remote_surface_set_snapped_to_left(wl_client* client,
+                                        wl_resource* resource);
+
+void remote_surface_set_snapped_to_right(wl_client* client,
+                                         wl_resource* resource);
+void remote_surface_start_resize(wl_client* client,
+                                 wl_resource* resource,
+                                 uint32_t direction,
+                                 int32_t x,
+                                 int32_t y);
+void remote_surface_set_frame(wl_client* client,
+                              wl_resource* resource,
+                              uint32_t type);
+void remote_surface_set_frame_buttons(wl_client* client,
+                                      wl_resource* resource,
+                                      uint32_t visible_button_mask,
+                                      uint32_t enabled_button_mask);
+void remote_surface_set_extra_title(wl_client* client,
+                                    wl_resource* resource,
+                                    const char* extra_title);
+void remote_surface_set_orientation_lock(wl_client* client,
+                                         wl_resource* resource,
+                                         uint32_t orientation_lock);
+void remote_surface_pip(wl_client* client, wl_resource* resource);
+void remote_surface_set_bounds(wl_client* client,
+                               wl_resource* resource,
+                               uint32_t display_id_hi,
+                               uint32_t display_id_lo,
+                               int32_t x,
+                               int32_t y,
+                               int32_t width,
+                               int32_t height);
+
+void remote_surface_set_accessibility_id(wl_client* client,
+                                         wl_resource* resource,
+                                         int32_t accessibility_id);
+void remote_surface_set_pip_original_window(wl_client* client,
+                                            wl_resource* resource);
+void remote_surface_unset_pip_original_window(wl_client* client,
+                                              wl_resource* resource);
+
+void remote_surface_set_system_gesture_exclusion(wl_client* client,
+                                                 wl_resource* resource,
+                                                 wl_resource* region_resource);
+void remote_surface_set_resize_lock(wl_client* client, wl_resource* resource);
+void remote_surface_unset_resize_lock(wl_client* client, wl_resource* resource);
+
+void remote_surface_set_bounds_in_output(wl_client* client,
+                                         wl_resource* resource,
+                                         wl_resource* output_resource,
+                                         int32_t x,
+                                         int32_t y,
+                                         int32_t width,
+                                         int32_t height);
+
+void remote_surface_block_ime(wl_client* client, wl_resource* resource);
+
+void remote_surface_unblock_ime(wl_client* client, wl_resource* resource);
+
+void remote_surface_set_window_type(wl_client* client,
+                                    wl_resource* resource,
+                                    uint32_t type);
+
+void remote_surface_set_scale(wl_client* client,
+                              wl_resource* resource,
+                              wl_fixed_t scale);
+
+void remote_surface_activate(wl_client* client,
+                             wl_resource* resource,
+                             uint32_t serial);
+
+void remote_surface_unfullscreen(wl_client* client, wl_resource* resource);
+
+void remote_surface_fullscreen(wl_client* client, wl_resource* resource);
+
+void remote_surface_ack_configure_DEPRECATED(wl_client* client,
+                                             wl_resource* resource,
+                                             uint32_t serial);
+
+void remote_surface_move_DEPRECATED(wl_client* client, wl_resource* resource);
+
+void remote_surface_resize_DEPRECATED(wl_client* client, wl_resource* resource);
+
+void remote_surface_set_resize_outset_DEPRECATED(wl_client* client,
+                                                 wl_resource* resource,
+                                                 int32_t outset);
+
+void remote_surface_set_rectangular_shadow_DEPRECATED(wl_client* client,
+                                                      wl_resource* resource,
+                                                      int32_t x,
+                                                      int32_t y,
+                                                      int32_t width,
+                                                      int32_t height);
+
+void remote_surface_set_rectangular_shadow_background_opacity_DEPRECATED(
+    wl_client* client,
+    wl_resource* resource,
+    wl_fixed_t opacity);
+
+////////////////////////////////////////////////////////////////////////////////
+// notification_surface_interface:
+
+void notification_surface_set_app_id(wl_client* client,
+                                     wl_resource* resource,
+                                     const char* app_id);
+
+////////////////////////////////////////////////////////////////////////////////
+// input_method_surface_interface:
+
+void input_method_surface_set_bounds_in_output(wl_client* client,
+                                               wl_resource* resource,
+                                               wl_resource* output_resource,
+                                               int32_t x,
+                                               int32_t y,
+                                               int32_t width,
+                                               int32_t height);
+
+void input_method_surface_set_bounds(wl_client* client,
+                                     wl_resource* resource,
+                                     uint32_t display_id_hi,
+                                     uint32_t display_id_lo,
+                                     int32_t x,
+                                     int32_t y,
+                                     int32_t width,
+                                     int32_t height);
+
+////////////////////////////////////////////////////////////////////////////////
+// toast_surface_interface:
+
+void toast_surface_set_bounds_in_output(wl_client* client,
+                                        wl_resource* resource,
+                                        wl_resource* output_resource,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height);
+
+void toast_surface_set_position(wl_client* client,
+                                wl_resource* resource,
+                                uint32_t display_id_hi,
+                                uint32_t display_id_lo,
+                                int32_t x,
+                                int32_t y);
+
+void toast_surface_set_size(wl_client* client,
+                            wl_resource* resource,
+                            int32_t width,
+                            int32_t height);
+
+void toast_surface_set_bounds_in_output(wl_client* client,
+                                        wl_resource* resource,
+                                        wl_resource* output_resource,
+                                        int32_t x,
+                                        int32_t y,
+                                        int32_t width,
+                                        int32_t height);
+
+////////////////////////////////////////////////////////////////////////////////
+// remote_shell_interface:
+
+void remote_shell_set_use_default_scale_cancellation(
+    wl_client*,
+    wl_resource* resource,
+    int32_t use_default_scale_cancellation);
+
+}  // namespace zcr_remote_shell
+}  // namespace wayland
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_IMPL_H_
diff --git a/components/exo/wayland/zcr_remote_shell_v2.cc b/components/exo/wayland/zcr_remote_shell_v2.cc
new file mode 100644
index 0000000..7edfaa0
--- /dev/null
+++ b/components/exo/wayland/zcr_remote_shell_v2.cc
@@ -0,0 +1,312 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <aura-shell-server-protocol.h>
+#include <remote-shell-unstable-v2-server-protocol.h>
+
+#include "ash/wm/desks/desks_util.h"
+#include "components/exo/wayland/server_util.h"
+#include "components/exo/wayland/zcr_remote_shell_impl.h"
+#include "components/exo/wm_helper_chromeos.h"
+
+namespace exo {
+namespace wayland {
+namespace {
+
+int RemoteSurfaceContainerV2(uint32_t container) {
+  switch (container) {
+    case ZCR_REMOTE_SHELL_V2_CONTAINER_DEFAULT:
+      return ash::desks_util::GetActiveDeskContainerId();
+    case ZCR_REMOTE_SHELL_V2_CONTAINER_OVERLAY:
+      return ash::kShellWindowId_SystemModalContainer;
+    default:
+      DLOG(WARNING) << "Unsupported container: " << container;
+      return ash::desks_util::GetActiveDeskContainerId();
+  }
+}
+
+const struct WaylandRemoteOutputEventMapping remote_output_event_mapping_v2 = {
+    zcr_remote_output_v2_send_identification_data,
+    // deprecated but not removed due to lack of alternative for stable
+    // identifier for wl_resource required on the ARC side.
+    zcr_remote_output_v2_send_display_id,
+    zcr_remote_output_v2_send_port,
+    zcr_remote_output_v2_send_insets,
+    zcr_remote_output_v2_send_stable_insets,
+    zcr_remote_output_v2_send_systemui_behavior,
+    ZCR_REMOTE_OUTPUT_V2_SYSTEMUI_BEHAVIOR_SINCE_VERSION,
+    ZCR_REMOTE_OUTPUT_V2_STABLE_INSETS_SINCE_VERSION,
+};
+
+const WaylandRemoteShellEventMapping wayland_remote_shell_event_mapping_v2 = {
+    zcr_remote_surface_v2_send_window_geometry_changed,
+    zcr_remote_surface_v2_send_change_zoom_level,
+    zcr_remote_surface_v2_send_state_type_changed,
+    zcr_remote_surface_v2_send_bounds_changed_in_output,
+    zcr_remote_surface_v2_send_bounds_changed,
+    nullptr,  // moved to zaura-shell protocol
+    zcr_remote_shell_v2_send_desktop_focus_state_changed,
+    nullptr,  // event removed in v2
+    zcr_remote_surface_v2_send_drag_finished,
+    zcr_remote_surface_v2_send_drag_started,
+    zcr_remote_shell_v2_send_layout_mode,
+    zcr_remote_shell_v2_send_default_device_scale_factor,
+    nullptr,  // event removed in v2
+    ZCR_REMOTE_SURFACE_V2_BOUNDS_CHANGED_IN_OUTPUT_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V2_DESKTOP_FOCUS_STATE_CHANGED_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V2_LAYOUT_MODE_SINCE_VERSION,
+    ZCR_REMOTE_SHELL_V2_DEFAULT_DEVICE_SCALE_FACTOR_SINCE_VERSION,
+    1,
+    1,
+    1,
+    1,
+};
+
+const struct zcr_remote_surface_v2_interface remote_surface_implementation_v2 =
+    {
+        +[](wl_client* client, wl_resource* resource) {
+          wl_resource_destroy(resource);
+        },
+        zcr_remote_shell::remote_surface_set_app_id,
+        zcr_remote_shell::remote_surface_set_title,
+        zcr_remote_shell::remote_surface_set_top_inset,
+        zcr_remote_shell::remote_surface_maximize,
+        zcr_remote_shell::remote_surface_minimize,
+        zcr_remote_shell::remote_surface_restore,
+        zcr_remote_shell::remote_surface_fullscreen,
+        zcr_remote_shell::remote_surface_pin,
+        zcr_remote_shell::remote_surface_unpin,
+        zcr_remote_shell::remote_surface_set_system_modal,
+        zcr_remote_shell::remote_surface_unset_system_modal,
+        zcr_remote_shell::remote_surface_set_rectangular_surface_shadow,
+        zcr_remote_shell::remote_surface_set_systemui_visibility,
+        zcr_remote_shell::remote_surface_set_always_on_top,
+        zcr_remote_shell::remote_surface_unset_always_on_top,
+        zcr_remote_shell::remote_surface_set_orientation,
+        zcr_remote_shell::remote_surface_start_move,
+        zcr_remote_shell::remote_surface_set_can_maximize,
+        zcr_remote_shell::remote_surface_unset_can_maximize,
+        zcr_remote_shell::remote_surface_set_min_size,
+        zcr_remote_shell::remote_surface_set_max_size,
+        zcr_remote_shell::remote_surface_set_snapped_to_left,
+        zcr_remote_shell::remote_surface_set_snapped_to_right,
+        zcr_remote_shell::remote_surface_start_resize,
+        zcr_remote_shell::remote_surface_set_frame,
+        zcr_remote_shell::remote_surface_set_frame_buttons,
+        zcr_remote_shell::remote_surface_set_extra_title,
+        zcr_remote_shell::remote_surface_set_orientation_lock,
+        zcr_remote_shell::remote_surface_pip,
+        zcr_remote_shell::remote_surface_set_aspect_ratio,
+        zcr_remote_shell::remote_surface_set_accessibility_id,
+        zcr_remote_shell::remote_surface_set_pip_original_window,
+        zcr_remote_shell::remote_surface_unset_pip_original_window,
+        zcr_remote_shell::remote_surface_set_system_gesture_exclusion,
+        zcr_remote_shell::remote_surface_set_resize_lock,
+        zcr_remote_shell::remote_surface_unset_resize_lock,
+        zcr_remote_shell::remote_surface_set_bounds_in_output,
+};
+
+const struct zcr_notification_surface_v2_interface
+    notification_surface_implementation_v2 = {
+        +[](wl_client* client, wl_resource* resource) {
+          wl_resource_destroy(resource);
+        },
+        zcr_remote_shell::notification_surface_set_app_id,
+};
+
+const struct zcr_input_method_surface_v2_interface
+    input_method_surface_implementation_v2 = {
+        +[](wl_client* client, wl_resource* resource) {
+          wl_resource_destroy(resource);
+        },
+        zcr_remote_shell::input_method_surface_set_bounds_in_output,
+};
+
+const struct zcr_toast_surface_v2_interface toast_surface_implementation_v2 = {
+    +[](wl_client* client, wl_resource* resource) {
+      wl_resource_destroy(resource);
+    },
+    zcr_remote_shell::toast_surface_set_bounds_in_output,
+};
+
+const struct zcr_remote_output_v2_interface remote_output_implementation_v2 = {
+    +[](wl_client* client, wl_resource* resource) {
+      wl_resource_destroy(resource);
+    },
+};
+
+void HandleRemoteSurfaceCloseCallbackV2(wl_resource* resource) {
+  zcr_remote_surface_v2_send_close(resource);
+  wl_client_flush(wl_resource_get_client(resource));
+}
+
+void remote_shell_get_remote_surface_v2(wl_client* client,
+                                        wl_resource* resource,
+                                        uint32_t id,
+                                        wl_resource* surface,
+                                        uint32_t container) {
+  WaylandRemoteShell* shell = GetUserDataAs<WaylandRemoteShell>(resource);
+  double default_scale_factor = zcr_remote_shell::GetDefaultDeviceScaleFactor();
+
+  std::unique_ptr<ClientControlledShellSurface> shell_surface =
+      shell->CreateShellSurface(GetUserDataAs<Surface>(surface),
+                                RemoteSurfaceContainerV2(container),
+                                default_scale_factor);
+  if (!shell_surface) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "surface has already been assigned a role");
+    return;
+  }
+
+  wl_resource* remote_surface_resource =
+      wl_resource_create(client, &zcr_remote_surface_v2_interface,
+                         wl_resource_get_version(resource), id);
+
+  shell_surface->set_delegate(
+      shell->CreateShellSurfaceDelegate(remote_surface_resource));
+  shell_surface->set_close_callback(
+      base::BindRepeating(&HandleRemoteSurfaceCloseCallbackV2,
+                          base::Unretained(remote_surface_resource)));
+  shell_surface->set_surface_destroyed_callback(base::BindOnce(
+      &wl_resource_destroy, base::Unretained(remote_surface_resource)));
+
+  SetImplementation(remote_surface_resource, &remote_surface_implementation_v2,
+                    std::move(shell_surface));
+}
+
+void remote_shell_get_notification_surface_v2(wl_client* client,
+                                              wl_resource* resource,
+                                              uint32_t id,
+                                              wl_resource* surface,
+                                              const char* notification_key) {
+  if (GetUserDataAs<Surface>(surface)->HasSurfaceDelegate()) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "surface has already been assigned a role");
+    return;
+  }
+
+  std::unique_ptr<NotificationSurface> notification_surface =
+      GetUserDataAs<WaylandRemoteShell>(resource)->CreateNotificationSurface(
+          GetUserDataAs<Surface>(surface), std::string(notification_key));
+  if (!notification_surface) {
+    wl_resource_post_error(resource,
+                           ZCR_REMOTE_SHELL_V2_ERROR_INVALID_NOTIFICATION_KEY,
+                           "invalid notification key");
+    return;
+  }
+
+  wl_resource* notification_surface_resource =
+      wl_resource_create(client, &zcr_notification_surface_v2_interface,
+                         wl_resource_get_version(resource), id);
+  SetImplementation(notification_surface_resource,
+                    &notification_surface_implementation_v2,
+                    std::move(notification_surface));
+}
+
+void remote_shell_get_input_method_surface_v2(wl_client* client,
+                                              wl_resource* resource,
+                                              uint32_t id,
+                                              wl_resource* surface) {
+  if (GetUserDataAs<Surface>(surface)->HasSurfaceDelegate()) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "surface has already been assigned a role");
+    return;
+  }
+
+  std::unique_ptr<ClientControlledShellSurface> input_method_surface =
+      GetUserDataAs<WaylandRemoteShell>(resource)->CreateInputMethodSurface(
+          GetUserDataAs<Surface>(surface),
+          zcr_remote_shell::GetDefaultDeviceScaleFactor());
+  if (!input_method_surface) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "Cannot create an IME surface");
+    return;
+  }
+
+  wl_resource* input_method_surface_resource =
+      wl_resource_create(client, &zcr_input_method_surface_v2_interface,
+                         wl_resource_get_version(resource), id);
+  SetImplementation(input_method_surface_resource,
+                    &input_method_surface_implementation_v2,
+                    std::move(input_method_surface));
+}
+
+void remote_shell_get_toast_surface_v2(wl_client* client,
+                                       wl_resource* resource,
+                                       uint32_t id,
+                                       wl_resource* surface) {
+  if (GetUserDataAs<Surface>(surface)->HasSurfaceDelegate()) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "surface has already been assigned a role");
+    return;
+  }
+
+  std::unique_ptr<ClientControlledShellSurface> toast_surface =
+      GetUserDataAs<WaylandRemoteShell>(resource)->CreateToastSurface(
+          GetUserDataAs<Surface>(surface),
+          zcr_remote_shell::GetDefaultDeviceScaleFactor());
+  if (!toast_surface) {
+    wl_resource_post_error(resource, ZCR_REMOTE_SHELL_V2_ERROR_ROLE,
+                           "Cannot create an toast surface");
+    return;
+  }
+
+  wl_resource* toast_surface_resource =
+      wl_resource_create(client, &zcr_toast_surface_v2_interface,
+                         wl_resource_get_version(resource), id);
+  SetImplementation(toast_surface_resource, &toast_surface_implementation_v2,
+                    std::move(toast_surface));
+}
+
+void remote_shell_get_remote_output_v2(wl_client* client,
+                                       wl_resource* resource,
+                                       uint32_t id,
+                                       wl_resource* output_resource) {
+  WaylandDisplayHandler* display_handler =
+      GetUserDataAs<WaylandDisplayHandler>(output_resource);
+
+  wl_resource* remote_output_resource =
+      wl_resource_create(client, &zcr_remote_output_v2_interface,
+                         wl_resource_get_version(resource), id);
+
+  auto remote_output = std::make_unique<WaylandRemoteOutput>(
+      remote_output_resource, remote_output_event_mapping_v2);
+  display_handler->AddObserver(remote_output.get());
+
+  SetImplementation(remote_output_resource, &remote_output_implementation_v2,
+                    std::move(remote_output));
+}
+
+const struct zcr_remote_shell_v2_interface remote_shell_implementation_v2 = {
+    +[](wl_client* client, wl_resource* resource) {
+      // Nothing to do here.
+    },
+    remote_shell_get_remote_surface_v2,
+    remote_shell_get_notification_surface_v2,
+    remote_shell_get_input_method_surface_v2,
+    remote_shell_get_toast_surface_v2,
+    remote_shell_get_remote_output_v2};
+
+}  // namespace
+
+void bind_remote_shell_v2(wl_client* client,
+                          void* data,
+                          uint32_t version,
+                          uint32_t id) {
+  wl_resource* resource = wl_resource_create(
+      client, &zcr_remote_shell_v2_interface,
+      std::min<uint32_t>(version, zcr_remote_shell_v2_interface.version), id);
+
+  auto* remote_shell_data = static_cast<WaylandRemoteShellData*>(data);
+  SetImplementation(
+      resource, &remote_shell_implementation_v2,
+      std::make_unique<WaylandRemoteShell>(
+          remote_shell_data->display, resource,
+          base::BindRepeating(remote_shell_data->output_provider, client),
+          wayland_remote_shell_event_mapping_v2,
+          /*use_default_scale_cancellation_default=*/false));
+}
+
+}  // namespace wayland
+}  // namespace exo
diff --git a/components/exo/wayland/zcr_remote_shell_v2.h b/components/exo/wayland/zcr_remote_shell_v2.h
new file mode 100644
index 0000000..4d06ca6
--- /dev/null
+++ b/components/exo/wayland/zcr_remote_shell_v2.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_V2_H_
+#define COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_V2_H_
+
+#include <stdint.h>
+
+#include "base/callback.h"
+
+struct wl_client;
+
+namespace exo {
+namespace wayland {
+
+void bind_remote_shell_v2(wl_client* client,
+                          void* data,
+                          uint32_t version,
+                          uint32_t id);
+}  // namespace wayland
+}  // namespace exo
+
+#endif  // COMPONENTS_EXO_WAYLAND_ZCR_REMOTE_SHELL_V2_H_
diff --git a/components/exo/wm_helper_chromeos.cc b/components/exo/wm_helper_chromeos.cc
index 95ec705d..bf706b5 100644
--- a/components/exo/wm_helper_chromeos.cc
+++ b/components/exo/wm_helper_chromeos.cc
@@ -68,8 +68,12 @@
 }
 
 void WMHelperChromeOS::AddFrameThrottlingObserver() {
-  ash::Shell::Get()->frame_throttling_controller()->AddArcObserver(
-      &vsync_timing_manager_);
+  ash::FrameThrottlingController* controller =
+      ash::Shell::Get()->frame_throttling_controller();
+  if (!controller->HasArcObserver(&vsync_timing_manager_)) {
+    ash::Shell::Get()->frame_throttling_controller()->AddArcObserver(
+        &vsync_timing_manager_);
+  }
 }
 
 void WMHelperChromeOS::RemoveFrameThrottlingObserver() {
diff --git a/components/messages/android/internal/java/res/layout/message_banner_view.xml b/components/messages/android/internal/java/res/layout/message_banner_view.xml
index 5ee51fb..697661a4 100644
--- a/components/messages/android/internal/java/res/layout/message_banner_view.xml
+++ b/components/messages/android/internal/java/res/layout/message_banner_view.xml
@@ -61,11 +61,12 @@
     <org.chromium.components.browser_ui.widget.listmenu.ListMenuButton
         android:id="@+id/message_secondary_button"
         app:tint="@color/default_icon_color_secondary"
+        app:menuVerticalOverlapAnchor="false"
         android:visibility="gone"
         android:contentDescription="@null"
+        android:background="?actionBarItemBackground"
         android:layout_width="@dimen/message_banner_button_width"
-        android:layout_height="match_parent"
-        android:background="@null" />
+        android:layout_height="@dimen/min_touch_target_size" />
 
     <ImageView
         android:id="@+id/message_divider"
diff --git a/components/optimization_guide/content/browser/BUILD.gn b/components/optimization_guide/content/browser/BUILD.gn
index af22e70b..5a1f571 100644
--- a/components/optimization_guide/content/browser/BUILD.gn
+++ b/components/optimization_guide/content/browser/BUILD.gn
@@ -39,6 +39,7 @@
     "//components/optimization_guide:optimization_guide_buildflags",
     "//components/optimization_guide/content/mojom:mojo_interfaces",
     "//components/optimization_guide/core",
+    "//components/optimization_guide/core:entities",
     "//components/optimization_guide/proto:optimization_guide_proto",
     "//content/public/browser",
     "//services/metrics/public/cpp:metrics_cpp",
diff --git a/components/optimization_guide/core/BUILD.gn b/components/optimization_guide/core/BUILD.gn
index ca9329f..5a2a82c 100644
--- a/components/optimization_guide/core/BUILD.gn
+++ b/components/optimization_guide/core/BUILD.gn
@@ -18,16 +18,25 @@
   ]
 }
 
-static_library("core") {
+static_library("entities") {
   sources = [
     "batch_entity_metadata_task.cc",
     "batch_entity_metadata_task.h",
+    "entity_metadata.h",
+    "entity_metadata_provider.h",
+  ]
+  public_deps = [
+    "//base",
+    "//third_party/abseil-cpp:absl",
+  ]
+}
+
+static_library("core") {
+  sources = [
     "command_line_top_host_provider.cc",
     "command_line_top_host_provider.h",
     "decision_tree_prediction_model.cc",
     "decision_tree_prediction_model.h",
-    "entity_metadata.h",
-    "entity_metadata_provider.h",
     "hint_cache.cc",
     "hint_cache.h",
     "hints_component_info.h",
@@ -106,6 +115,7 @@
   ]
   if (build_with_tflite_lib) {
     public_deps += [
+      ":entities",
       "//components/optimization_guide/core:machine_learning",
       "//third_party/tflite",
       "//third_party/tflite:tflite_public_headers",
@@ -209,6 +219,7 @@
   deps = [
     ":bloomfilter",
     ":core",
+    ":entities",
     ":test_support",
     "//base",
     "//base/test:test_support",
diff --git a/components/policy/core/common/policy_loader_win.cc b/components/policy/core/common/policy_loader_win.cc
index ef3f8a0c..5a7a2def 100644
--- a/components/policy/core/common/policy_loader_win.cc
+++ b/components/policy/core/common/policy_loader_win.cc
@@ -4,11 +4,15 @@
 
 #include "components/policy/core/common/policy_loader_win.h"
 
+// Must be included before lm.h
+#include <windows.h>
+
 #include <lm.h>       // For NetGetJoinInformation
 // <security.h> needs this.
 #define SECURITY_WIN32 1
 #include <security.h>  // For GetUserNameEx()
 #include <stddef.h>
+#include <userenv.h>
 
 #include <memory>
 #include <string>
diff --git a/components/policy/core/common/policy_loader_win.h b/components/policy/core/common/policy_loader_win.h
index a094f71..d48c6c2 100644
--- a/components/policy/core/common/policy_loader_win.h
+++ b/components/policy/core/common/policy_loader_win.h
@@ -5,10 +5,6 @@
 #ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_LOADER_WIN_H_
 #define COMPONENTS_POLICY_CORE_COMMON_POLICY_LOADER_WIN_H_
 
-#include <windows.h>
-
-#include <userenv.h>
-
 #include <memory>
 #include <string>
 
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index b0664418..2ba49f2 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -2980,12 +2980,19 @@
 
 // Contains information about the TPM used on the device.
 message TpmVersionInfo {
+  enum GscVersion {
+    GSC_VERSION_UNSPECIFIED = 0;
+    GSC_VERSION_NOT_GSC = 1;
+    GSC_VERSION_CR50 = 2;
+    GSC_VERSION_TI50 = 3;
+  }
   optional uint32 family = 1;
   optional uint64 spec_level = 2;
   optional uint32 manufacturer = 3;
   optional uint32 tpm_model = 4;
   optional uint64 firmware_version = 5;
   optional string vendor_specific = 6;
+  optional GscVersion gsc_version = 7;
 }
 
 // Contains status of the TPM unit.
diff --git a/components/signin/public/base/signin_metrics.cc b/components/signin/public/base/signin_metrics.cc
index 5012c8e..bae2aac 100644
--- a/components/signin/public/base/signin_metrics.cc
+++ b/components/signin/public/base/signin_metrics.cc
@@ -522,16 +522,6 @@
       break;                                                                   \
   }
 
-// Helper method to determine which |DifferentPrimaryAccounts| applies.
-DifferentPrimaryAccounts ComparePrimaryAccounts(bool primary_accounts_same,
-                                                int pre_count_gaia_cookies) {
-  if (primary_accounts_same)
-    return ACCOUNTS_SAME;
-  if (pre_count_gaia_cookies == 0)
-    return NO_COOKIE_PRESENT;
-  return COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT;
-}
-
 void LogSigninAccessPointStarted(AccessPoint access_point,
                                  PromoAction promo_action) {
   UMA_HISTOGRAM_ENUMERATION("Signin.SigninStartedAccessPoint",
@@ -606,37 +596,6 @@
   UMA_HISTOGRAM_ENUMERATION("Signin.SigninReason", reason);
 }
 
-void LogSigninAccountReconciliation(int total_number_accounts,
-                                    int count_added_to_cookie_jar,
-                                    int count_removed_from_cookie_jar,
-                                    bool primary_accounts_same,
-                                    bool is_first_reconcile,
-                                    int pre_count_gaia_cookies) {
-  RecordAccountsPerProfile(total_number_accounts);
-  // We want to include zeroes in the counts of added or removed accounts to
-  // easily capture _relatively_ how often we merge accounts.
-  if (is_first_reconcile) {
-    UMA_HISTOGRAM_COUNTS_100("Signin.Reconciler.AddedToCookieJar.FirstRun",
-                             count_added_to_cookie_jar);
-    UMA_HISTOGRAM_COUNTS_100("Signin.Reconciler.RemovedFromCookieJar.FirstRun",
-                             count_removed_from_cookie_jar);
-    UMA_HISTOGRAM_ENUMERATION(
-        "Signin.Reconciler.DifferentPrimaryAccounts.FirstRun",
-        ComparePrimaryAccounts(primary_accounts_same, pre_count_gaia_cookies),
-        NUM_DIFFERENT_PRIMARY_ACCOUNT_METRICS);
-  } else {
-    UMA_HISTOGRAM_COUNTS_100("Signin.Reconciler.AddedToCookieJar.SubsequentRun",
-                             count_added_to_cookie_jar);
-    UMA_HISTOGRAM_COUNTS_100(
-        "Signin.Reconciler.RemovedFromCookieJar.SubsequentRun",
-        count_removed_from_cookie_jar);
-    UMA_HISTOGRAM_ENUMERATION(
-        "Signin.Reconciler.DifferentPrimaryAccounts.SubsequentRun",
-        ComparePrimaryAccounts(primary_accounts_same, pre_count_gaia_cookies),
-        NUM_DIFFERENT_PRIMARY_ACCOUNT_METRICS);
-  }
-}
-
 void RecordAccountsPerProfile(int total_number_accounts) {
   UMA_HISTOGRAM_COUNTS_100("Profile.NumberOfAccountsPerProfile",
                            total_number_accounts);
diff --git a/components/signin/public/base/signin_metrics.h b/components/signin/public/base/signin_metrics.h
index 6bd53cc..e4bd627 100644
--- a/components/signin/public/base/signin_metrics.h
+++ b/components/signin/public/base/signin_metrics.h
@@ -13,19 +13,6 @@
 
 namespace signin_metrics {
 
-// Enum for the ways in which primary account detection is done.
-enum DifferentPrimaryAccounts {
-  // token and cookie had same primary accounts.
-  ACCOUNTS_SAME = 0,
-  // Deprecated. Indicates different primary accounts.
-  UNUSED_ACCOUNTS_DIFFERENT,
-  // No GAIA cookie present, so the primaries are considered different.
-  NO_COOKIE_PRESENT,
-  // There was at least one cookie and one token, and the primaries differed.
-  COOKIE_AND_TOKEN_PRIMARIES_DIFFERENT,
-  NUM_DIFFERENT_PRIMARY_ACCOUNT_METRICS,
-};
-
 // Track all the ways a profile can become signed out as a histogram.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.components.signin.metrics
 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: SignoutReason
@@ -457,27 +444,6 @@
 // Tracks the reason of sign in.
 void LogSigninReason(Reason reason);
 
-// Log to UMA histograms and UserCounts stats about a single execution of the
-// AccountReconciler.
-// |total_number_accounts| - How many accounts are in the browser for this
-//                           profile.
-// |count_added_to_cookie_jar| - How many accounts were in the browser but not
-//                               in the cookie jar.
-// |count_removed_from_cookie_jar| - How many accounts were in the cookie jar
-//                                   but not in the browser.
-// |primary_accounts_same| - False if the primary account for the cookie jar
-//                           and the token service were different; else true.
-// |is_first_reconcile| - True if these stats are from the first execution of
-//                        the AccountReconcilor.
-// |pre_count_gaia_cookies| - How many GAIA cookies were present before
-//                            the AccountReconcilor began modifying the state.
-void LogSigninAccountReconciliation(int total_number_accounts,
-                                    int count_added_to_cookie_jar,
-                                    int count_removed_from_cookie_jar,
-                                    bool primary_accounts_same,
-                                    bool is_first_reconcile,
-                                    int pre_count_gaia_cookies);
-
 // Logs to UMA histograms how many accounts are in the browser for this
 // profile.
 void RecordAccountsPerProfile(int total_number_accounts);
diff --git a/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc b/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
index d126eea3..bafe4df 100644
--- a/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
+++ b/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
@@ -71,7 +71,7 @@
   // activity is being recreated or destroyed, ads blocked message will not be
   // displayed.
   message_dispatcher_bridge->EnqueueMessage(
-      message.get(), web_contents(), messages::MessageScopeType::WEB_CONTENTS,
+      message.get(), web_contents(), messages::MessageScopeType::NAVIGATION,
       messages::MessagePriority::kNormal);
 
   message_ = std::move(message);
diff --git a/components/sync/base/model_type_test_util.cc b/components/sync/base/model_type_test_util.cc
index 8378b290..c62be72 100644
--- a/components/sync/base/model_type_test_util.cc
+++ b/components/sync/base/model_type_test_util.cc
@@ -20,6 +20,9 @@
   explicit HasModelTypesMatcher(ModelTypeSet expected_types)
       : expected_types_(expected_types) {}
 
+  HasModelTypesMatcher(const HasModelTypesMatcher&) = delete;
+  HasModelTypesMatcher& operator=(const HasModelTypesMatcher&) = delete;
+
   virtual ~HasModelTypesMatcher() {}
 
   virtual bool MatchAndExplain(ModelTypeSet model_types,
@@ -38,8 +41,6 @@
 
  private:
   const ModelTypeSet expected_types_;
-
-  DISALLOW_COPY_AND_ASSIGN(HasModelTypesMatcher);
 };
 
 }  // namespace
diff --git a/components/sync/base/sync_prefs.h b/components/sync/base/sync_prefs.h
index 95b3eb5..b90deb1 100644
--- a/components/sync/base/sync_prefs.h
+++ b/components/sync/base/sync_prefs.h
@@ -41,6 +41,10 @@
  public:
   // |pref_service| must not be null and must outlive this object.
   explicit SyncPrefs(PrefService* pref_service);
+
+  SyncPrefs(const SyncPrefs&) = delete;
+  SyncPrefs& operator=(const SyncPrefs&) = delete;
+
   ~SyncPrefs();
 
   static void RegisterProfilePrefs(PrefRegistrySimple* registry);
@@ -155,8 +159,6 @@
   bool local_sync_enabled_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(SyncPrefs);
 };
 
 void ClearObsoletePassphrasePromptPrefs(PrefService* pref_service);
diff --git a/components/sync/driver/backend_migrator.h b/components/sync/driver/backend_migrator.h
index 7ee6f78..b29e9cd 100644
--- a/components/sync/driver/backend_migrator.h
+++ b/components/sync/driver/backend_migrator.h
@@ -43,6 +43,10 @@
                   DataTypeManager* manager,
                   const base::RepeatingClosure& reconfigure_callback,
                   const base::RepeatingClosure& migration_done_callback);
+
+  BackendMigrator(const BackendMigrator&) = delete;
+  BackendMigrator& operator=(const BackendMigrator&) = delete;
+
   virtual ~BackendMigrator();
 
   // Starts a sequence of events that will disable and reenable |types|.
@@ -88,8 +92,6 @@
   ModelTypeSet to_migrate_;
 
   base::WeakPtrFactory<BackendMigrator> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(BackendMigrator);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/data_type_manager_impl.h b/components/sync/driver/data_type_manager_impl.h
index 7cb9f4a..40508ae 100644
--- a/components/sync/driver/data_type_manager_impl.h
+++ b/components/sync/driver/data_type_manager_impl.h
@@ -35,6 +35,10 @@
       const DataTypeEncryptionHandler* encryption_handler,
       ModelTypeConfigurer* configurer,
       DataTypeManagerObserver* observer);
+
+  DataTypeManagerImpl(const DataTypeManagerImpl&) = delete;
+  DataTypeManagerImpl& operator=(const DataTypeManagerImpl&) = delete;
+
   ~DataTypeManagerImpl() override;
 
   // DataTypeManager interface.
@@ -225,8 +229,6 @@
   std::map<ModelType, DataTypeConfigurationStats> configuration_stats_;
 
   base::WeakPtrFactory<DataTypeManagerImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(DataTypeManagerImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/glue/sync_engine_impl.h b/components/sync/driver/glue/sync_engine_impl.h
index 0d9eab05..da2526e 100644
--- a/components/sync/driver/glue/sync_engine_impl.h
+++ b/components/sync/driver/glue/sync_engine_impl.h
@@ -60,6 +60,10 @@
                  const base::FilePath& sync_data_folder,
                  scoped_refptr<base::SequencedTaskRunner> sync_task_runner,
                  const base::RepeatingClosure& sync_transport_data_cleared_cb);
+
+  SyncEngineImpl(const SyncEngineImpl&) = delete;
+  SyncEngineImpl& operator=(const SyncEngineImpl&) = delete;
+
   ~SyncEngineImpl() override;
 
   // SyncEngine implementation.
@@ -219,8 +223,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<SyncEngineImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncEngineImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/model_load_manager.h b/components/sync/driver/model_load_manager.h
index 02517ca..3f9fbf9b 100644
--- a/components/sync/driver/model_load_manager.h
+++ b/components/sync/driver/model_load_manager.h
@@ -44,6 +44,10 @@
  public:
   ModelLoadManager(const DataTypeController::TypeMap* controllers,
                    ModelLoadManagerDelegate* delegate);
+
+  ModelLoadManager(const ModelLoadManager&) = delete;
+  ModelLoadManager& operator=(const ModelLoadManager&) = delete;
+
   virtual ~ModelLoadManager();
 
   // Stops any data types that are *not* in |desired_types|, then kicks off
@@ -99,8 +103,6 @@
   bool notified_about_ready_for_configure_ = false;
 
   base::WeakPtrFactory<ModelLoadManager> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ModelLoadManager);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/model_type_controller.h b/components/sync/driver/model_type_controller.h
index 4738652..030f55f8 100644
--- a/components/sync/driver/model_type_controller.h
+++ b/components/sync/driver/model_type_controller.h
@@ -36,6 +36,10 @@
       ModelType type,
       std::unique_ptr<ModelTypeControllerDelegate> delegate_for_full_sync_mode,
       std::unique_ptr<ModelTypeControllerDelegate> delegate_for_transport_mode);
+
+  ModelTypeController(const ModelTypeController&) = delete;
+  ModelTypeController& operator=(const ModelTypeController&) = delete;
+
   ~ModelTypeController() override;
 
   // DataTypeController implementation.
@@ -98,8 +102,6 @@
   // ClientTagBasedModelTypeProcessor callback and must temporarily own it until
   // Connect is called.
   std::unique_ptr<DataTypeActivationResponse> activation_response_;
-
-  DISALLOW_COPY_AND_ASSIGN(ModelTypeController);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc
index 911b0a0..b05fbec2 100644
--- a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc
+++ b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.cc
@@ -4,6 +4,7 @@
 
 #include "components/sync/driver/non_ui_syncable_service_based_model_type_controller.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/bind.h"
@@ -44,6 +45,9 @@
                        std::move(syncable_service_provider), dump_stack));
   }
 
+  BridgeBuilder(const BridgeBuilder&) = delete;
+  BridgeBuilder& operator=(const BridgeBuilder&) = delete;
+
   ~BridgeBuilder() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); }
 
   // Indirectly called for each operation by ProxyModelTypeControllerDelegate.
@@ -76,8 +80,6 @@
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   std::unique_ptr<ModelTypeSyncBridge> bridge_;
-
-  DISALLOW_COPY_AND_ASSIGN(BridgeBuilder);
 };
 
 // This is a slightly adapted version of base::OnTaskRunnerDeleter: The one
diff --git a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.h b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.h
index 3ae3027..145ddcd5 100644
--- a/components/sync/driver/non_ui_syncable_service_based_model_type_controller.h
+++ b/components/sync/driver/non_ui_syncable_service_based_model_type_controller.h
@@ -42,10 +42,13 @@
       const base::RepeatingClosure& dump_stack,
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       bool allow_transport_mode = false);
-  ~NonUiSyncableServiceBasedModelTypeController() override;
 
- private:
-  DISALLOW_COPY_AND_ASSIGN(NonUiSyncableServiceBasedModelTypeController);
+  NonUiSyncableServiceBasedModelTypeController(
+      const NonUiSyncableServiceBasedModelTypeController&) = delete;
+  NonUiSyncableServiceBasedModelTypeController& operator=(
+      const NonUiSyncableServiceBasedModelTypeController&) = delete;
+
+  ~NonUiSyncableServiceBasedModelTypeController() override;
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_auth_manager.h b/components/sync/driver/sync_auth_manager.h
index 7ab45fe..9d5bdd5 100644
--- a/components/sync/driver/sync_auth_manager.h
+++ b/components/sync/driver/sync_auth_manager.h
@@ -52,6 +52,10 @@
   SyncAuthManager(signin::IdentityManager* identity_manager,
                   const AccountStateChangedCallback& account_state_changed,
                   const CredentialsChangedCallback& credentials_changed);
+
+  SyncAuthManager(const SyncAuthManager&) = delete;
+  SyncAuthManager& operator=(const SyncAuthManager&) = delete;
+
   ~SyncAuthManager() override;
 
   // Tells the tracker to start listening for changes to the account/sign-in
@@ -202,8 +206,6 @@
   bool access_token_retried_ = false;
 
   base::WeakPtrFactory<SyncAuthManager> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncAuthManager);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_client_mock.h b/components/sync/driver/sync_client_mock.h
index 986f2fa..ee7824f 100644
--- a/components/sync/driver/sync_client_mock.h
+++ b/components/sync/driver/sync_client_mock.h
@@ -14,6 +14,10 @@
 class SyncClientMock : public SyncClient {
  public:
   SyncClientMock();
+
+  SyncClientMock(const SyncClientMock&) = delete;
+  SyncClientMock& operator=(const SyncClientMock&) = delete;
+
   ~SyncClientMock() override;
   MOCK_METHOD(PrefService*, GetPrefService, (), (override));
   MOCK_METHOD(signin::IdentityManager*, GetIdentityManager, (), (override));
@@ -44,9 +48,6 @@
               (),
               (override));
   MOCK_METHOD(void, OnLocalSyncTransportDataCleared, (), (override));
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncClientMock);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_policy_handler.h b/components/sync/driver/sync_policy_handler.h
index 4293c8c..d89c07f8 100644
--- a/components/sync/driver/sync_policy_handler.h
+++ b/components/sync/driver/sync_policy_handler.h
@@ -19,14 +19,15 @@
 class SyncPolicyHandler : public policy::TypeCheckingPolicyHandler {
  public:
   SyncPolicyHandler();
+
+  SyncPolicyHandler(const SyncPolicyHandler&) = delete;
+  SyncPolicyHandler& operator=(const SyncPolicyHandler&) = delete;
+
   ~SyncPolicyHandler() override;
 
   // ConfigurationPolicyHandler methods:
   void ApplyPolicySettings(const policy::PolicyMap& policies,
                            PrefValueMap* prefs) override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncPolicyHandler);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_service.h b/components/sync/driver/sync_service.h
index 5decdb4..38e9f87 100644
--- a/components/sync/driver/sync_service.h
+++ b/components/sync/driver/sync_service.h
@@ -174,6 +174,9 @@
     ACTIVE
   };
 
+  SyncService(const SyncService&) = delete;
+  SyncService& operator=(const SyncService&) = delete;
+
   ~SyncService() override {}
 
   //////////////////////////////////////////////////////////////////////////////
@@ -434,9 +437,6 @@
 
  protected:
   SyncService() {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncService);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_service_crypto.h b/components/sync/driver/sync_service_crypto.h
index 0e65140..35952dd 100644
--- a/components/sync/driver/sync_service_crypto.h
+++ b/components/sync/driver/sync_service_crypto.h
@@ -43,6 +43,10 @@
   // outlive this object.
   SyncServiceCrypto(Delegate* delegate,
                     TrustedVaultClient* trusted_vault_client);
+
+  SyncServiceCrypto(const SyncServiceCrypto&) = delete;
+  SyncServiceCrypto& operator=(const SyncServiceCrypto&) = delete;
+
   ~SyncServiceCrypto() override;
 
   void Reset();
@@ -210,8 +214,6 @@
   bool initial_trusted_vault_recoverability_logged_to_uma_ = false;
 
   base::WeakPtrFactory<SyncServiceCrypto> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncServiceCrypto);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_service_impl.h b/components/sync/driver/sync_service_impl.h
index 6a1cc486..1a32d4d 100644
--- a/components/sync/driver/sync_service_impl.h
+++ b/components/sync/driver/sync_service_impl.h
@@ -78,6 +78,10 @@
   struct InitParams {
     InitParams();
     InitParams(InitParams&& other);
+
+    InitParams(const InitParams&) = delete;
+    InitParams& operator=(const InitParams&) = delete;
+
     ~InitParams();
 
     std::unique_ptr<SyncClient> sync_client;
@@ -90,13 +94,13 @@
     version_info::Channel channel = version_info::Channel::UNKNOWN;
     std::string debug_identifier;
     policy::PolicyService* policy_service = nullptr;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(InitParams);
   };
 
   explicit SyncServiceImpl(InitParams init_params);
 
+  SyncServiceImpl(const SyncServiceImpl&) = delete;
+  SyncServiceImpl& operator=(const SyncServiceImpl&) = delete;
+
   ~SyncServiceImpl() override;
 
   // Initializes the object. This must be called at most once, and
@@ -463,8 +467,6 @@
   base::WeakPtrFactory<SyncServiceImpl> sync_enabled_weak_factory_{this};
 
   base::WeakPtrFactory<SyncServiceImpl> weak_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncServiceImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_session_durations_metrics_recorder.h b/components/sync/driver/sync_session_durations_metrics_recorder.h
index 56675d0..8f68ea7 100644
--- a/components/sync/driver/sync_session_durations_metrics_recorder.h
+++ b/components/sync/driver/sync_session_durations_metrics_recorder.h
@@ -26,6 +26,12 @@
   SyncSessionDurationsMetricsRecorder(
       SyncService* sync_service,
       signin::IdentityManager* identity_manager);
+
+  SyncSessionDurationsMetricsRecorder(
+      const SyncSessionDurationsMetricsRecorder&) = delete;
+  SyncSessionDurationsMetricsRecorder& operator=(
+      const SyncSessionDurationsMetricsRecorder&) = delete;
+
   ~SyncSessionDurationsMetricsRecorder() override;
 
   // Informs this service that a session started at |session_start| time.
@@ -102,8 +108,6 @@
   // Tracks the elapsed active session time in the current sync and account
   // status. The timer is absent if there's no active session.
   std::unique_ptr<base::ElapsedTimer> sync_account_session_timer_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncSessionDurationsMetricsRecorder);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/sync_session_durations_metrics_recorder_unittest.cc b/components/sync/driver/sync_session_durations_metrics_recorder_unittest.cc
index cb71faea..7e3385bc 100644
--- a/components/sync/driver/sync_session_durations_metrics_recorder_unittest.cc
+++ b/components/sync/driver/sync_session_durations_metrics_recorder_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/task_environment.h"
@@ -28,6 +29,11 @@
     sync_service_.SetDisableReasons(SyncService::DISABLE_REASON_NOT_SIGNED_IN);
   }
 
+  SyncSessionDurationsMetricsRecorderTest(
+      const SyncSessionDurationsMetricsRecorderTest&) = delete;
+  SyncSessionDurationsMetricsRecorderTest& operator=(
+      const SyncSessionDurationsMetricsRecorderTest&) = delete;
+
   ~SyncSessionDurationsMetricsRecorderTest() override {}
 
   void EnableSync() {
@@ -95,8 +101,6 @@
   network::TestURLLoaderFactory test_url_loader_factory_;
   signin::IdentityTestEnvironment identity_test_env_;
   TestSyncService sync_service_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncSessionDurationsMetricsRecorderTest);
 };
 
 TEST_F(SyncSessionDurationsMetricsRecorderTest, WebSignedOut) {
diff --git a/components/sync/driver/sync_stopped_reporter.h b/components/sync/driver/sync_stopped_reporter.h
index a0763bc..d2fd5bd 100644
--- a/components/sync/driver/sync_stopped_reporter.h
+++ b/components/sync/driver/sync_stopped_reporter.h
@@ -32,6 +32,10 @@
       const std::string& user_agent,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       ResultCallback callback);
+
+  SyncStoppedReporter(const SyncStoppedReporter&) = delete;
+  SyncStoppedReporter& operator=(const SyncStoppedReporter&) = delete;
+
   ~SyncStoppedReporter();
 
   // Inform the sync server that sync was stopped on this device.
@@ -68,8 +72,6 @@
 
   // A callback for request completion or timeout.
   ResultCallback callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncStoppedReporter);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/syncable_service_based_model_type_controller.cc b/components/sync/driver/syncable_service_based_model_type_controller.cc
index 032274a6..1e29f3fc 100644
--- a/components/sync/driver/syncable_service_based_model_type_controller.cc
+++ b/components/sync/driver/syncable_service_based_model_type_controller.cc
@@ -37,6 +37,9 @@
     }
   }
 
+  ControllerDelegate(const ControllerDelegate&) = delete;
+  ControllerDelegate& operator=(const ControllerDelegate&) = delete;
+
   ~ControllerDelegate() override {}
 
   void OnSyncStarting(const DataTypeActivationRequest& request,
@@ -71,8 +74,6 @@
   const ModelType type_;
   const base::RepeatingClosure dump_stack_;
   std::unique_ptr<ModelTypeSyncBridge> bridge_;
-
-  DISALLOW_COPY_AND_ASSIGN(ControllerDelegate);
 };
 
 }  // namespace
diff --git a/components/sync/driver/syncable_service_based_model_type_controller.h b/components/sync/driver/syncable_service_based_model_type_controller.h
index 462b31b..fa1c685 100644
--- a/components/sync/driver/syncable_service_based_model_type_controller.h
+++ b/components/sync/driver/syncable_service_based_model_type_controller.h
@@ -34,14 +34,17 @@
       const base::RepeatingClosure& dump_stack,
       DelegateMode delegate_mode = DelegateMode::kFullSyncModeOnly);
 
+  SyncableServiceBasedModelTypeController(
+      const SyncableServiceBasedModelTypeController&) = delete;
+  SyncableServiceBasedModelTypeController& operator=(
+      const SyncableServiceBasedModelTypeController&) = delete;
+
   ~SyncableServiceBasedModelTypeController() override;
 
  private:
   // Delegate owned by this instance; delegate instances passed to the base
   // class forward their calls to |delegate_|.
   std::unique_ptr<ModelTypeControllerDelegate> delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncableServiceBasedModelTypeController);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/test_sync_service.h b/components/sync/driver/test_sync_service.h
index 1eaefc3..dcd6b57 100644
--- a/components/sync/driver/test_sync_service.h
+++ b/components/sync/driver/test_sync_service.h
@@ -26,6 +26,10 @@
 class TestSyncService : public SyncService {
  public:
   TestSyncService();
+
+  TestSyncService(const TestSyncService&) = delete;
+  TestSyncService& operator=(const TestSyncService&) = delete;
+
   ~TestSyncService() override;
 
   void SetDisableReasons(DisableReasonSet disable_reasons);
@@ -135,8 +139,6 @@
   base::ObserverList<syncer::SyncServiceObserver>::Unchecked observers_;
 
   GURL sync_service_url_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestSyncService);
 };
 
 }  // namespace syncer
diff --git a/components/sync/driver/trusted_vault_client.h b/components/sync/driver/trusted_vault_client.h
index 0fd9411..9dd815e 100644
--- a/components/sync/driver/trusted_vault_client.h
+++ b/components/sync/driver/trusted_vault_client.h
@@ -36,6 +36,10 @@
   };
 
   TrustedVaultClient() = default;
+
+  TrustedVaultClient(const TrustedVaultClient&) = delete;
+  TrustedVaultClient& operator=(const TrustedVaultClient&) = delete;
+
   virtual ~TrustedVaultClient() = default;
 
   // Adds/removes an observer.
@@ -87,9 +91,6 @@
                                         const std::vector<uint8_t>& public_key,
                                         int method_type_hint,
                                         base::OnceClosure cb) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(TrustedVaultClient);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/backoff_delay_provider.h b/components/sync/engine/backoff_delay_provider.h
index c06582e7..b064777 100644
--- a/components/sync/engine/backoff_delay_provider.h
+++ b/components/sync/engine/backoff_delay_provider.h
@@ -28,6 +28,9 @@
   // was passed to command line.
   static std::unique_ptr<BackoffDelayProvider> WithShortInitialRetryOverride();
 
+  BackoffDelayProvider(const BackoffDelayProvider&) = delete;
+  BackoffDelayProvider& operator=(const BackoffDelayProvider&) = delete;
+
   virtual ~BackoffDelayProvider();
 
   // DDOS avoidance function.  Calculates how long we should wait before trying
@@ -52,8 +55,6 @@
  private:
   const base::TimeDelta default_initial_backoff_;
   const base::TimeDelta short_initial_backoff_;
-
-  DISALLOW_COPY_AND_ASSIGN(BackoffDelayProvider);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/commit.h b/components/sync/engine/commit.h
index 0538b30..71fe72c2 100644
--- a/components/sync/engine/commit.h
+++ b/components/sync/engine/commit.h
@@ -43,6 +43,9 @@
          const sync_pb::ClientToServerMessage& message,
          ExtensionsActivity::Records extensions_activity_buffer);
 
+  Commit(const Commit&) = delete;
+  Commit& operator=(const Commit&) = delete;
+
   ~Commit();
 
   // |extensions_activity| may be null.
@@ -73,8 +76,6 @@
 
   sync_pb::ClientToServerMessage message_;
   ExtensionsActivity::Records extensions_activity_buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(Commit);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/commit_contribution_impl.h b/components/sync/engine/commit_contribution_impl.h
index 0e537e8e..43eca375 100644
--- a/components/sync/engine/commit_contribution_impl.h
+++ b/components/sync/engine/commit_contribution_impl.h
@@ -49,6 +49,10 @@
       Cryptographer* cryptographer,
       PassphraseType passphrase_type,
       bool only_commit_specifics);
+
+  CommitContributionImpl(const CommitContributionImpl&) = delete;
+  CommitContributionImpl& operator=(const CommitContributionImpl&) = delete;
+
   ~CommitContributionImpl() override;
 
   // Implementation of CommitContribution
@@ -102,8 +106,6 @@
   // Don't send any metadata to server, only specifics. This is needed for
   // commit only types to save bandwidth.
   bool only_commit_specifics_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommitContributionImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/commit_processor.h b/components/sync/engine/commit_processor.h
index e6bd76da..b084952 100644
--- a/components/sync/engine/commit_processor.h
+++ b/components/sync/engine/commit_processor.h
@@ -27,6 +27,10 @@
   // null and must outlive this object.
   CommitProcessor(ModelTypeSet commit_types,
                   CommitContributorMap* commit_contributor_map);
+
+  CommitProcessor(const CommitProcessor&) = delete;
+  CommitProcessor& operator=(const CommitProcessor&) = delete;
+
   ~CommitProcessor();
 
   // Gathers a set of contributions to be used to populate a commit message.
@@ -71,8 +75,6 @@
   // A map of 'commit contributors', one for each enabled type.
   CommitContributorMap* commit_contributor_map_;
   GatheringPhase phase_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommitProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/data_type_tracker.h b/components/sync/engine/cycle/data_type_tracker.h
index fa1ee79..39c4780 100644
--- a/components/sync/engine/cycle/data_type_tracker.h
+++ b/components/sync/engine/cycle/data_type_tracker.h
@@ -49,6 +49,10 @@
 class DataTypeTracker {
  public:
   explicit DataTypeTracker(ModelType type);
+
+  DataTypeTracker(const DataTypeTracker&) = delete;
+  DataTypeTracker& operator=(const DataTypeTracker&) = delete;
+
   ~DataTypeTracker();
 
   // For STL compatibility, we do not forbid the creation of a default copy
@@ -199,8 +203,6 @@
   // The amount of time to delay a sync cycle by when a local change for this
   // type occurs.
   base::TimeDelta local_change_nudge_delay_;
-
-  DISALLOW_COPY_AND_ASSIGN(DataTypeTracker);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/mock_debug_info_getter.h b/components/sync/engine/cycle/mock_debug_info_getter.h
index 2da1401..0c170c3 100644
--- a/components/sync/engine/cycle/mock_debug_info_getter.h
+++ b/components/sync/engine/cycle/mock_debug_info_getter.h
@@ -17,6 +17,10 @@
 class MockDebugInfoGetter : public DebugInfoGetter {
  public:
   MockDebugInfoGetter();
+
+  MockDebugInfoGetter(const MockDebugInfoGetter&) = delete;
+  MockDebugInfoGetter& operator=(const MockDebugInfoGetter&) = delete;
+
   ~MockDebugInfoGetter() override;
 
   // DebugInfoGetter implementation.
@@ -27,8 +31,6 @@
 
  private:
   sync_pb::DebugInfo debug_info_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockDebugInfoGetter);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/nudge_tracker.h b/components/sync/engine/cycle/nudge_tracker.h
index dee8c7f..61240e5 100644
--- a/components/sync/engine/cycle/nudge_tracker.h
+++ b/components/sync/engine/cycle/nudge_tracker.h
@@ -30,6 +30,10 @@
 class NudgeTracker {
  public:
   NudgeTracker();
+
+  NudgeTracker(const NudgeTracker&) = delete;
+  NudgeTracker& operator=(const NudgeTracker&) = delete;
+
   ~NudgeTracker();
 
   // Returns true if there is a good reason for performing a sync cycle.
@@ -203,8 +207,6 @@
   // SetSyncCycleStartTime().  This may contain a stale value if we're not
   // currently in a sync cycle.
   base::TimeTicks sync_cycle_start_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(NudgeTracker);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/status_controller.h b/components/sync/engine/cycle/status_controller.h
index d1385cb3..6af31ca 100644
--- a/components/sync/engine/cycle/status_controller.h
+++ b/components/sync/engine/cycle/status_controller.h
@@ -25,6 +25,10 @@
 class StatusController {
  public:
   StatusController();
+
+  StatusController(const StatusController&) = delete;
+  StatusController& operator=(const StatusController&) = delete;
+
   ~StatusController();
 
   // The types included in the get updates client to server requests.
@@ -92,8 +96,6 @@
   // If a poll was performed, the time it finished. Not set if not poll was
   // performed.
   base::Time poll_finish_time_;
-
-  DISALLOW_COPY_AND_ASSIGN(StatusController);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/cycle/sync_cycle_context.h b/components/sync/engine/cycle/sync_cycle_context.h
index 3aeaef8..c36f0068 100644
--- a/components/sync/engine/cycle/sync_cycle_context.h
+++ b/components/sync/engine/cycle/sync_cycle_context.h
@@ -50,6 +50,9 @@
                    const std::string& bag_of_chips,
                    base::TimeDelta poll_interval);
 
+  SyncCycleContext(const SyncCycleContext&) = delete;
+  SyncCycleContext& operator=(const SyncCycleContext&) = delete;
+
   ~SyncCycleContext();
 
   ServerConnectionManager* connection_manager() { return connection_manager_; }
@@ -180,8 +183,6 @@
   ActiveDevicesInvalidationInfo active_devices_invalidation_info_;
 
   base::TimeDelta poll_interval_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncCycleContext);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/debug_info_event_listener.h b/components/sync/engine/debug_info_event_listener.h
index 1a02123d..66cfb003 100644
--- a/components/sync/engine/debug_info_event_listener.h
+++ b/components/sync/engine/debug_info_event_listener.h
@@ -42,6 +42,10 @@
                                public DataTypeDebugInfoListener {
  public:
   DebugInfoEventListener();
+
+  DebugInfoEventListener(const DebugInfoEventListener&) = delete;
+  DebugInfoEventListener& operator=(const DebugInfoEventListener&) = delete;
+
   ~DebugInfoEventListener() override;
 
   void InitializationComplete();
@@ -113,8 +117,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<DebugInfoEventListener> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(DebugInfoEventListener);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/commit_request_event.h b/components/sync/engine/events/commit_request_event.h
index 5fac2f40..93672f16 100644
--- a/components/sync/engine/events/commit_request_event.h
+++ b/components/sync/engine/events/commit_request_event.h
@@ -25,6 +25,10 @@
                      size_t num_items,
                      ModelTypeSet contributing_types,
                      const sync_pb::ClientToServerMessage& request);
+
+  CommitRequestEvent(const CommitRequestEvent&) = delete;
+  CommitRequestEvent& operator=(const CommitRequestEvent&) = delete;
+
   ~CommitRequestEvent() override;
 
   std::unique_ptr<ProtocolEvent> Clone() const override;
@@ -40,8 +44,6 @@
   const size_t num_items_;
   const ModelTypeSet contributing_types_;
   const sync_pb::ClientToServerMessage request_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommitRequestEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/commit_response_event.h b/components/sync/engine/events/commit_response_event.h
index e5924ff95..8ebd343 100644
--- a/components/sync/engine/events/commit_response_event.h
+++ b/components/sync/engine/events/commit_response_event.h
@@ -24,6 +24,10 @@
   CommitResponseEvent(base::Time timestamp,
                       SyncerError result,
                       const sync_pb::ClientToServerResponse& response);
+
+  CommitResponseEvent(const CommitResponseEvent&) = delete;
+  CommitResponseEvent& operator=(const CommitResponseEvent&) = delete;
+
   ~CommitResponseEvent() override;
   std::unique_ptr<ProtocolEvent> Clone() const override;
 
@@ -40,8 +44,6 @@
   const base::Time timestamp_;
   const SyncerError result_;
   const sync_pb::ClientToServerResponse response_;
-
-  DISALLOW_COPY_AND_ASSIGN(CommitResponseEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/configure_get_updates_request_event.h b/components/sync/engine/events/configure_get_updates_request_event.h
index b31b182..f58538e 100644
--- a/components/sync/engine/events/configure_get_updates_request_event.h
+++ b/components/sync/engine/events/configure_get_updates_request_event.h
@@ -24,6 +24,12 @@
       base::Time timestamp,
       sync_pb::SyncEnums::GetUpdatesOrigin origin,
       const sync_pb::ClientToServerMessage& request);
+
+  ConfigureGetUpdatesRequestEvent(const ConfigureGetUpdatesRequestEvent&) =
+      delete;
+  ConfigureGetUpdatesRequestEvent& operator=(
+      const ConfigureGetUpdatesRequestEvent&) = delete;
+
   ~ConfigureGetUpdatesRequestEvent() override;
   std::unique_ptr<ProtocolEvent> Clone() const override;
 
@@ -37,8 +43,6 @@
   const base::Time timestamp_;
   const sync_pb::SyncEnums::GetUpdatesOrigin origin_;
   const sync_pb::ClientToServerMessage request_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConfigureGetUpdatesRequestEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/get_updates_response_event.h b/components/sync/engine/events/get_updates_response_event.h
index 9ed08bf..7467a3fa 100644
--- a/components/sync/engine/events/get_updates_response_event.h
+++ b/components/sync/engine/events/get_updates_response_event.h
@@ -27,6 +27,9 @@
                           const sync_pb::ClientToServerResponse& response,
                           SyncerError error);
 
+  GetUpdatesResponseEvent(const GetUpdatesResponseEvent&) = delete;
+  GetUpdatesResponseEvent& operator=(const GetUpdatesResponseEvent&) = delete;
+
   ~GetUpdatesResponseEvent() override;
   std::unique_ptr<ProtocolEvent> Clone() const override;
 
@@ -40,8 +43,6 @@
   const base::Time timestamp_;
   const sync_pb::ClientToServerResponse response_;
   const SyncerError error_;
-
-  DISALLOW_COPY_AND_ASSIGN(GetUpdatesResponseEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/normal_get_updates_request_event.h b/components/sync/engine/events/normal_get_updates_request_event.h
index d021604..a8c4285 100644
--- a/components/sync/engine/events/normal_get_updates_request_event.h
+++ b/components/sync/engine/events/normal_get_updates_request_event.h
@@ -31,6 +31,11 @@
                                ModelTypeSet refresh_requested_types,
                                bool is_retry,
                                sync_pb::ClientToServerMessage request);
+
+  NormalGetUpdatesRequestEvent(const NormalGetUpdatesRequestEvent&) = delete;
+  NormalGetUpdatesRequestEvent& operator=(const NormalGetUpdatesRequestEvent&) =
+      delete;
+
   ~NormalGetUpdatesRequestEvent() override;
   std::unique_ptr<ProtocolEvent> Clone() const override;
 
@@ -49,8 +54,6 @@
   const bool is_retry_;
 
   const sync_pb::ClientToServerMessage request_;
-
-  DISALLOW_COPY_AND_ASSIGN(NormalGetUpdatesRequestEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/poll_get_updates_request_event.h b/components/sync/engine/events/poll_get_updates_request_event.h
index 30e6c91e3..220b5134 100644
--- a/components/sync/engine/events/poll_get_updates_request_event.h
+++ b/components/sync/engine/events/poll_get_updates_request_event.h
@@ -22,6 +22,11 @@
  public:
   PollGetUpdatesRequestEvent(base::Time timestamp,
                              const sync_pb::ClientToServerMessage& request);
+
+  PollGetUpdatesRequestEvent(const PollGetUpdatesRequestEvent&) = delete;
+  PollGetUpdatesRequestEvent& operator=(const PollGetUpdatesRequestEvent&) =
+      delete;
+
   ~PollGetUpdatesRequestEvent() override;
   std::unique_ptr<ProtocolEvent> Clone() const override;
 
@@ -34,8 +39,6 @@
 
   const base::Time timestamp_;
   const sync_pb::ClientToServerMessage request_;
-
-  DISALLOW_COPY_AND_ASSIGN(PollGetUpdatesRequestEvent);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/events/protocol_event_buffer.h b/components/sync/engine/events/protocol_event_buffer.h
index a092e823..e1afc3ff 100644
--- a/components/sync/engine/events/protocol_event_buffer.h
+++ b/components/sync/engine/events/protocol_event_buffer.h
@@ -25,6 +25,10 @@
   static const size_t kBufferSize;
 
   ProtocolEventBuffer();
+
+  ProtocolEventBuffer(const ProtocolEventBuffer&) = delete;
+  ProtocolEventBuffer& operator=(const ProtocolEventBuffer&) = delete;
+
   ~ProtocolEventBuffer();
 
   // Records an event.  May cause the oldest event to be dropped.
@@ -35,8 +39,6 @@
 
  private:
   base::circular_deque<std::unique_ptr<ProtocolEvent>> buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProtocolEventBuffer);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/forwarding_model_type_processor.h b/components/sync/engine/forwarding_model_type_processor.h
index 1cfaef2..863b91f 100644
--- a/components/sync/engine/forwarding_model_type_processor.h
+++ b/components/sync/engine/forwarding_model_type_processor.h
@@ -20,6 +20,11 @@
  public:
   // |processor| must not be null and must outlive this object.
   explicit ForwardingModelTypeProcessor(ModelTypeProcessor* processor);
+
+  ForwardingModelTypeProcessor(const ForwardingModelTypeProcessor&) = delete;
+  ForwardingModelTypeProcessor& operator=(const ForwardingModelTypeProcessor&) =
+      delete;
+
   ~ForwardingModelTypeProcessor() override;
 
   void ConnectSync(std::unique_ptr<CommitQueue> worker) override;
@@ -36,8 +41,6 @@
 
  private:
   ModelTypeProcessor* const processor_;
-
-  DISALLOW_COPY_AND_ASSIGN(ForwardingModelTypeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/get_updates_delegate.h b/components/sync/engine/get_updates_delegate.h
index 42d86c7c..0949aff 100644
--- a/components/sync/engine/get_updates_delegate.h
+++ b/components/sync/engine/get_updates_delegate.h
@@ -28,6 +28,10 @@
 class GetUpdatesDelegate {
  public:
   GetUpdatesDelegate() = default;
+
+  GetUpdatesDelegate(const GetUpdatesDelegate&) = delete;
+  GetUpdatesDelegate& operator=(const GetUpdatesDelegate&) = delete;
+
   virtual ~GetUpdatesDelegate() = default;
 
   // Populates GetUpdate message fields that depend on GetUpdates request type.
@@ -37,15 +41,16 @@
   virtual std::unique_ptr<ProtocolEvent> GetNetworkRequestEvent(
       base::Time timestamp,
       const sync_pb::ClientToServerMessage& request) const = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(GetUpdatesDelegate);
 };
 
 // Functionality specific to the normal GetUpdate request.
 class NormalGetUpdatesDelegate : public GetUpdatesDelegate {
  public:
   explicit NormalGetUpdatesDelegate(const NudgeTracker& nudge_tracker);
+
+  NormalGetUpdatesDelegate(const NormalGetUpdatesDelegate&) = delete;
+  NormalGetUpdatesDelegate& operator=(const NormalGetUpdatesDelegate&) = delete;
+
   ~NormalGetUpdatesDelegate() override;
 
   // Uses the member NudgeTracker to populate some fields of this GU message.
@@ -58,8 +63,6 @@
 
  private:
   const NudgeTracker& nudge_tracker_;
-
-  DISALLOW_COPY_AND_ASSIGN(NormalGetUpdatesDelegate);
 };
 
 // Functionality specific to the configure GetUpdate request.
@@ -67,6 +70,11 @@
  public:
   explicit ConfigureGetUpdatesDelegate(
       sync_pb::SyncEnums::GetUpdatesOrigin origin);
+
+  ConfigureGetUpdatesDelegate(const ConfigureGetUpdatesDelegate&) = delete;
+  ConfigureGetUpdatesDelegate& operator=(const ConfigureGetUpdatesDelegate&) =
+      delete;
+
   ~ConfigureGetUpdatesDelegate() override;
 
   // Sets the 'source' and 'origin' fields for this request.
@@ -79,14 +87,16 @@
 
  private:
   const sync_pb::SyncEnums::GetUpdatesOrigin origin_;
-
-  DISALLOW_COPY_AND_ASSIGN(ConfigureGetUpdatesDelegate);
 };
 
 // Functionality specific to the poll GetUpdate request.
 class PollGetUpdatesDelegate : public GetUpdatesDelegate {
  public:
   PollGetUpdatesDelegate();
+
+  PollGetUpdatesDelegate(const PollGetUpdatesDelegate&) = delete;
+  PollGetUpdatesDelegate& operator=(const PollGetUpdatesDelegate&) = delete;
+
   ~PollGetUpdatesDelegate() override;
 
   // Sets the 'source' and 'origin' to indicate this is a poll request.
@@ -96,9 +106,6 @@
   std::unique_ptr<ProtocolEvent> GetNetworkRequestEvent(
       base::Time timestamp,
       const sync_pb::ClientToServerMessage& request) const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PollGetUpdatesDelegate);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/get_updates_processor.h b/components/sync/engine/get_updates_processor.h
index 22a3ec4..f4c4d210 100644
--- a/components/sync/engine/get_updates_processor.h
+++ b/components/sync/engine/get_updates_processor.h
@@ -32,6 +32,10 @@
  public:
   explicit GetUpdatesProcessor(UpdateHandlerMap* update_handler_map,
                                const GetUpdatesDelegate& delegate);
+
+  GetUpdatesProcessor(const GetUpdatesProcessor&) = delete;
+  GetUpdatesProcessor& operator=(const GetUpdatesProcessor&) = delete;
+
   ~GetUpdatesProcessor();
 
   // Downloads and processes a batch of updates for the specified types.
@@ -88,8 +92,6 @@
   UpdateHandlerMap* update_handler_map_;
 
   const GetUpdatesDelegate& delegate_;
-
-  DISALLOW_COPY_AND_ASSIGN(GetUpdatesProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/loopback_server/loopback_connection_manager.h b/components/sync/engine/loopback_server/loopback_connection_manager.h
index cfc195e..795d26d 100644
--- a/components/sync/engine/loopback_server/loopback_connection_manager.h
+++ b/components/sync/engine/loopback_server/loopback_connection_manager.h
@@ -19,6 +19,11 @@
 class LoopbackConnectionManager : public ServerConnectionManager {
  public:
   explicit LoopbackConnectionManager(const base::FilePath& persistent_file);
+
+  LoopbackConnectionManager(const LoopbackConnectionManager&) = delete;
+  LoopbackConnectionManager& operator=(const LoopbackConnectionManager&) =
+      delete;
+
   ~LoopbackConnectionManager() override;
 
  private:
@@ -29,8 +34,6 @@
 
   // The loopback server that will handle the requests locally.
   LoopbackServer loopback_server_;
-
-  DISALLOW_COPY_AND_ASSIGN(LoopbackConnectionManager);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/model_type_configurer.h b/components/sync/engine/model_type_configurer.h
index cba291c..a69eda73 100644
--- a/components/sync/engine/model_type_configurer.h
+++ b/components/sync/engine/model_type_configurer.h
@@ -24,6 +24,10 @@
   struct ConfigureParams {
     ConfigureParams();
     ConfigureParams(ConfigureParams&& other);
+
+    ConfigureParams(const ConfigureParams&) = delete;
+    ConfigureParams& operator=(const ConfigureParams&) = delete;
+
     ~ConfigureParams();
     ConfigureParams& operator=(ConfigureParams&& other);
 
@@ -36,9 +40,6 @@
 
     // Whether full sync (or sync the feature) is enabled;
     bool is_sync_feature_enabled;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(ConfigureParams);
   };
 
   ModelTypeConfigurer();
diff --git a/components/sync/engine/model_type_registry.h b/components/sync/engine/model_type_registry.h
index 754ed88..c67ee27 100644
--- a/components/sync/engine/model_type_registry.h
+++ b/components/sync/engine/model_type_registry.h
@@ -39,6 +39,10 @@
   ModelTypeRegistry(NudgeHandler* nudge_handler,
                     CancelationSignal* cancelation_signal,
                     SyncEncryptionHandler* sync_encryption_handler);
+
+  ModelTypeRegistry(const ModelTypeRegistry&) = delete;
+  ModelTypeRegistry& operator=(const ModelTypeRegistry&) = delete;
+
   ~ModelTypeRegistry() override;
 
   // Implementation of ModelTypeConnector.
@@ -108,8 +112,6 @@
   SyncEncryptionHandler* const sync_encryption_handler_;
 
   base::WeakPtrFactory<ModelTypeRegistry> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ModelTypeRegistry);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/model_type_worker.h b/components/sync/engine/model_type_worker.h
index 68da87a..3d24b38e 100644
--- a/components/sync/engine/model_type_worker.h
+++ b/components/sync/engine/model_type_worker.h
@@ -87,6 +87,10 @@
                   PassphraseType passphrase_type,
                   NudgeHandler* nudge_handler,
                   CancelationSignal* cancelation_signal);
+
+  ModelTypeWorker(const ModelTypeWorker&) = delete;
+  ModelTypeWorker& operator=(const ModelTypeWorker&) = delete;
+
   ~ModelTypeWorker() override;
 
   // Public for testing.
@@ -293,8 +297,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<ModelTypeWorker> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ModelTypeWorker);
 };
 
 // GetLocalChangesRequest is a container for GetLocalChanges call response. It
diff --git a/components/sync/engine/net/http_bridge.h b/components/sync/engine/net/http_bridge.h
index 959b4f7..447aeaa 100644
--- a/components/sync/engine/net/http_bridge.h
+++ b/components/sync/engine/net/http_bridge.h
@@ -189,6 +189,10 @@
   HttpBridgeFactory(const std::string& user_agent,
                     std::unique_ptr<network::PendingSharedURLLoaderFactory>
                         pending_url_loader_factory);
+
+  HttpBridgeFactory(const HttpBridgeFactory&) = delete;
+  HttpBridgeFactory& operator=(const HttpBridgeFactory&) = delete;
+
   ~HttpBridgeFactory() override;
 
   // HttpPostProviderFactory:
@@ -200,8 +204,6 @@
 
   // The URL loader factory used for making all requests.
   scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(HttpBridgeFactory);
 };
 
 }  //  namespace syncer
diff --git a/components/sync/engine/net/server_connection_manager.h b/components/sync/engine/net/server_connection_manager.h
index 6a7f7e05..ef60b6bf 100644
--- a/components/sync/engine/net/server_connection_manager.h
+++ b/components/sync/engine/net/server_connection_manager.h
@@ -92,6 +92,10 @@
 class ServerConnectionManager {
  public:
   ServerConnectionManager();
+
+  ServerConnectionManager(const ServerConnectionManager&) = delete;
+  ServerConnectionManager& operator=(const ServerConnectionManager&) = delete;
+
   virtual ~ServerConnectionManager();
 
   // POSTs |buffer_in| and reads the body of the response into |buffer_out|.
@@ -148,8 +152,6 @@
   HttpResponse server_response_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(ServerConnectionManager);
 };
 
 std::ostream& operator<<(std::ostream& s, const struct HttpResponse& hr);
diff --git a/components/sync/engine/net/sync_server_connection_manager.cc b/components/sync/engine/net/sync_server_connection_manager.cc
index a8484a0..daa8f1b 100644
--- a/components/sync/engine/net/sync_server_connection_manager.cc
+++ b/components/sync/engine/net/sync_server_connection_manager.cc
@@ -26,6 +26,10 @@
   // All pointers must not be null and must outlive this object.
   Connection(HttpPostProviderFactory* factory,
              CancelationSignal* cancelation_signal);
+
+  Connection(const Connection&) = delete;
+  Connection& operator=(const Connection&) = delete;
+
   ~Connection() override;
 
   HttpResponse Init(const GURL& connection_url,
@@ -51,8 +55,6 @@
   scoped_refptr<HttpPostProviderInterface> const post_provider_;
 
   std::string buffer_;
-
-  DISALLOW_COPY_AND_ASSIGN(Connection);
 };
 
 Connection::Connection(HttpPostProviderFactory* factory,
diff --git a/components/sync/engine/net/sync_server_connection_manager.h b/components/sync/engine/net/sync_server_connection_manager.h
index 8dcf3a7..650c696a 100644
--- a/components/sync/engine/net/sync_server_connection_manager.h
+++ b/components/sync/engine/net/sync_server_connection_manager.h
@@ -28,6 +28,11 @@
   SyncServerConnectionManager(const GURL& sync_request_url,
                               std::unique_ptr<HttpPostProviderFactory> factory,
                               CancelationSignal* cancelation_signal);
+
+  SyncServerConnectionManager(const SyncServerConnectionManager&) = delete;
+  SyncServerConnectionManager& operator=(const SyncServerConnectionManager&) =
+      delete;
+
   ~SyncServerConnectionManager() override;
 
   HttpResponse PostBuffer(const std::string& buffer_in,
@@ -45,8 +50,6 @@
   // Cancelation signal is signalled when engine shuts down. Current blocking
   // operation should be aborted.
   CancelationSignal* const cancelation_signal_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncServerConnectionManager);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/nigori/keystore_keys_handler.h b/components/sync/engine/nigori/keystore_keys_handler.h
index 3295a274..56a46853 100644
--- a/components/sync/engine/nigori/keystore_keys_handler.h
+++ b/components/sync/engine/nigori/keystore_keys_handler.h
@@ -15,6 +15,10 @@
 class KeystoreKeysHandler {
  public:
   KeystoreKeysHandler() = default;
+
+  KeystoreKeysHandler(const KeystoreKeysHandler&) = delete;
+  KeystoreKeysHandler& operator=(const KeystoreKeysHandler&) = delete;
+
   virtual ~KeystoreKeysHandler() = default;
 
   // Whether a keystore key needs to be requested from the sync server.
@@ -24,9 +28,6 @@
   // Returns true on success, false otherwise.
   virtual bool SetKeystoreKeys(
       const std::vector<std::vector<uint8_t>>& keys) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(KeystoreKeysHandler);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/sync_engine.h b/components/sync/engine/sync_engine.h
index dcd6865..e085d05 100644
--- a/components/sync/engine/sync_engine.h
+++ b/components/sync/engine/sync_engine.h
@@ -49,6 +49,10 @@
   struct InitParams {
     InitParams();
     InitParams(InitParams&& other);
+
+    InitParams(const InitParams&) = delete;
+    InitParams& operator=(const InitParams&) = delete;
+
     ~InitParams();
 
     SyncEngineHost* host = nullptr;
@@ -63,12 +67,13 @@
     base::FilePath local_sync_backend_folder;
     std::unique_ptr<EngineComponentsFactory> engine_components_factory;
     std::string encryption_bootstrap_token;
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(InitParams);
   };
 
   SyncEngine();
+
+  SyncEngine(const SyncEngine&) = delete;
+  SyncEngine& operator=(const SyncEngine&) = delete;
+
   ~SyncEngine() override;
 
   // Kicks off asynchronous initialization. Optionally deletes sync data during
@@ -174,9 +179,6 @@
 
   // Returns a ListValue representing Nigori node.
   virtual void GetNigoriNodeForDebugging(AllNodesCallback callback) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncEngine);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/sync_manager_factory.h b/components/sync/engine/sync_manager_factory.h
index 23f95c1..ed96e5f 100644
--- a/components/sync/engine/sync_manager_factory.h
+++ b/components/sync/engine/sync_manager_factory.h
@@ -23,6 +23,10 @@
  public:
   SyncManagerFactory(
       network::NetworkConnectionTracker* network_connection_tracker);
+
+  SyncManagerFactory(const SyncManagerFactory&) = delete;
+  SyncManagerFactory& operator=(const SyncManagerFactory&) = delete;
+
   virtual ~SyncManagerFactory();
 
   virtual std::unique_ptr<SyncManager> CreateSyncManager(
@@ -30,8 +34,6 @@
 
  private:
   network::NetworkConnectionTracker* network_connection_tracker_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncManagerFactory);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/sync_manager_impl.h b/components/sync/engine/sync_manager_impl.h
index a9e012e5..761013f 100644
--- a/components/sync/engine/sync_manager_impl.h
+++ b/components/sync/engine/sync_manager_impl.h
@@ -48,6 +48,10 @@
   SyncManagerImpl(
       const std::string& name,
       network::NetworkConnectionTracker* network_connection_tracker);
+
+  SyncManagerImpl(const SyncManagerImpl&) = delete;
+  SyncManagerImpl& operator=(const SyncManagerImpl&) = delete;
+
   ~SyncManagerImpl() override;
 
   // SyncManager implementation.
@@ -168,8 +172,6 @@
   std::unique_ptr<SyncEncryptionHandler::Observer> encryption_observer_proxy_;
 
   base::WeakPtrFactory<SyncManagerImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncManagerImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/sync_scheduler_impl.h b/components/sync/engine/sync_scheduler_impl.h
index 6fba055..7562336 100644
--- a/components/sync/engine/sync_scheduler_impl.h
+++ b/components/sync/engine/sync_scheduler_impl.h
@@ -40,6 +40,9 @@
                     std::unique_ptr<Syncer> syncer,
                     bool ignore_auth_credentials);
 
+  SyncSchedulerImpl(const SyncSchedulerImpl&) = delete;
+  SyncSchedulerImpl& operator=(const SyncSchedulerImpl&) = delete;
+
   // Calls Stop().
   ~SyncSchedulerImpl() override;
 
@@ -294,8 +297,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<SyncSchedulerImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncSchedulerImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine/syncer.h b/components/sync/engine/syncer.h
index 886ae99..c07fc381 100644
--- a/components/sync/engine/syncer.h
+++ b/components/sync/engine/syncer.h
@@ -32,6 +32,10 @@
 class Syncer {
  public:
   explicit Syncer(CancelationSignal* cancelation_signal);
+
+  Syncer(const Syncer&) = delete;
+  Syncer& operator=(const Syncer&) = delete;
+
   virtual ~Syncer();
 
   // Whether the syncer is in the middle of a sync cycle.
@@ -89,8 +93,6 @@
 
   // Whether the syncer is in the middle of a sync attempt.
   bool is_syncing_;
-
-  DISALLOW_COPY_AND_ASSIGN(Syncer);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/blocking_model_type_store_impl.h b/components/sync/model/blocking_model_type_store_impl.h
index 91d8851..19e9a22 100644
--- a/components/sync/model/blocking_model_type_store_impl.h
+++ b/components/sync/model/blocking_model_type_store_impl.h
@@ -22,6 +22,11 @@
   // |backend| must not be null.
   BlockingModelTypeStoreImpl(ModelType type,
                              scoped_refptr<ModelTypeStoreBackend> backend);
+
+  BlockingModelTypeStoreImpl(const BlockingModelTypeStoreImpl&) = delete;
+  BlockingModelTypeStoreImpl& operator=(const BlockingModelTypeStoreImpl&) =
+      delete;
+
   ~BlockingModelTypeStoreImpl() override;
 
   // BlockingModelTypeStore implementation.
@@ -52,8 +57,6 @@
   const std::string global_metadata_key_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(BlockingModelTypeStoreImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/client_tag_based_model_type_processor.h b/components/sync/model/client_tag_based_model_type_processor.h
index 829a551..e0ad5c6 100644
--- a/components/sync/model/client_tag_based_model_type_processor.h
+++ b/components/sync/model/client_tag_based_model_type_processor.h
@@ -54,6 +54,12 @@
   ClientTagBasedModelTypeProcessor(ModelType type,
                                    const base::RepeatingClosure& dump_stack,
                                    bool commit_only);
+
+  ClientTagBasedModelTypeProcessor(const ClientTagBasedModelTypeProcessor&) =
+      delete;
+  ClientTagBasedModelTypeProcessor& operator=(
+      const ClientTagBasedModelTypeProcessor&) = delete;
+
   ~ClientTagBasedModelTypeProcessor() override;
 
   // Returns true if the handshake with sync thread is complete.
@@ -299,8 +305,6 @@
   // WeakPtrFactory for this processor which will be sent to sync thread.
   base::WeakPtrFactory<ClientTagBasedModelTypeProcessor>
       weak_ptr_factory_for_worker_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ClientTagBasedModelTypeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/data_type_error_handler_impl.h b/components/sync/model/data_type_error_handler_impl.h
index b1256ad8..5cf04b0 100644
--- a/components/sync/model/data_type_error_handler_impl.h
+++ b/components/sync/model/data_type_error_handler_impl.h
@@ -24,6 +24,10 @@
       const scoped_refptr<base::SequencedTaskRunner>& ui_thread,
       const base::RepeatingClosure& dump_stack,
       const ErrorCallback& sync_callback);
+
+  DataTypeErrorHandlerImpl(const DataTypeErrorHandlerImpl&) = delete;
+  DataTypeErrorHandlerImpl& operator=(const DataTypeErrorHandlerImpl&) = delete;
+
   ~DataTypeErrorHandlerImpl() override;
 
   void OnUnrecoverableError(const SyncError& error) override;
@@ -43,8 +47,6 @@
 
   // The callback used to inform sync of the error on the |ui_thread_|.
   ErrorCallback sync_callback_;
-
-  DISALLOW_COPY_AND_ASSIGN(DataTypeErrorHandlerImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/entity_change.h b/components/sync/model/entity_change.h
index f554a2f3..c31ad222 100644
--- a/components/sync/model/entity_change.h
+++ b/components/sync/model/entity_change.h
@@ -26,6 +26,9 @@
   static std::unique_ptr<EntityChange> CreateDelete(
       const std::string& storage_key);
 
+  EntityChange(const EntityChange&) = delete;
+  EntityChange& operator=(const EntityChange&) = delete;
+
   virtual ~EntityChange();
 
   std::string storage_key() const { return storage_key_; }
@@ -40,8 +43,6 @@
   std::string storage_key_;
   ChangeType type_;
   EntityData data_;
-
-  DISALLOW_COPY_AND_ASSIGN(EntityChange);
 };
 
 using EntityChangeList = std::vector<std::unique_ptr<EntityChange>>;
diff --git a/components/sync/model/forwarding_model_type_controller_delegate.h b/components/sync/model/forwarding_model_type_controller_delegate.h
index f8c10843..6b1cf45 100644
--- a/components/sync/model/forwarding_model_type_controller_delegate.h
+++ b/components/sync/model/forwarding_model_type_controller_delegate.h
@@ -21,6 +21,12 @@
   // Except for tests, |other| must not be null and must outlive this object.
   explicit ForwardingModelTypeControllerDelegate(
       ModelTypeControllerDelegate* other);
+
+  ForwardingModelTypeControllerDelegate(
+      const ForwardingModelTypeControllerDelegate&) = delete;
+  ForwardingModelTypeControllerDelegate& operator=(
+      const ForwardingModelTypeControllerDelegate&) = delete;
+
   ~ForwardingModelTypeControllerDelegate() override;
 
   // ModelTypeControllerDelegate implementation.
@@ -35,8 +41,6 @@
 
  private:
   ModelTypeControllerDelegate* const other_;
-
-  DISALLOW_COPY_AND_ASSIGN(ForwardingModelTypeControllerDelegate);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/model_type_store_base.h b/components/sync/model/model_type_store_base.h
index b0570db..f7f2aed 100644
--- a/components/sync/model/model_type_store_base.h
+++ b/components/sync/model/model_type_store_base.h
@@ -35,6 +35,10 @@
     static std::unique_ptr<MetadataChangeList> CreateMetadataChangeList();
 
     WriteBatch();
+
+    WriteBatch(const WriteBatch&) = delete;
+    WriteBatch& operator=(const WriteBatch&) = delete;
+
     virtual ~WriteBatch();
 
     // Write the given |value| for data with |id|.
@@ -52,9 +56,6 @@
     // TODO(mastiz): Revisit whether the last requirement above can be removed
     // and make this API more type-safe.
     void TakeMetadataChangesFrom(std::unique_ptr<MetadataChangeList> mcl);
-
-   private:
-    DISALLOW_COPY_AND_ASSIGN(WriteBatch);
   };
 
   using RecordList = std::vector<Record>;
diff --git a/components/sync/model/model_type_store_impl.h b/components/sync/model/model_type_store_impl.h
index c47b6c3..68d93b02 100644
--- a/components/sync/model/model_type_store_impl.h
+++ b/components/sync/model/model_type_store_impl.h
@@ -30,6 +30,10 @@
       std::unique_ptr<BlockingModelTypeStoreImpl, base::OnTaskRunnerDeleter>
           backend_store,
       scoped_refptr<base::SequencedTaskRunner> backend_task_runner);
+
+  ModelTypeStoreImpl(const ModelTypeStoreImpl&) = delete;
+  ModelTypeStoreImpl& operator=(const ModelTypeStoreImpl&) = delete;
+
   ~ModelTypeStoreImpl() override;
 
   // ModelTypeStore implementation.
@@ -70,8 +74,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<ModelTypeStoreImpl> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(ModelTypeStoreImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/model_type_store_service_impl.h b/components/sync/model/model_type_store_service_impl.h
index 0bcb6f0d..753f9e1 100644
--- a/components/sync/model/model_type_store_service_impl.h
+++ b/components/sync/model/model_type_store_service_impl.h
@@ -22,6 +22,11 @@
  public:
   // |base_path| represents the profile's path.
   explicit ModelTypeStoreServiceImpl(const base::FilePath& base_path);
+
+  ModelTypeStoreServiceImpl(const ModelTypeStoreServiceImpl&) = delete;
+  ModelTypeStoreServiceImpl& operator=(const ModelTypeStoreServiceImpl&) =
+      delete;
+
   ~ModelTypeStoreServiceImpl() override;
 
   // ModelTypeStoreService:
@@ -45,8 +50,6 @@
   const scoped_refptr<ModelTypeStoreBackend> store_backend_;
 
   SEQUENCE_CHECKER(ui_sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(ModelTypeStoreServiceImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/mutable_data_batch.h b/components/sync/model/mutable_data_batch.h
index ced7d16b..6e1c442 100644
--- a/components/sync/model/mutable_data_batch.h
+++ b/components/sync/model/mutable_data_batch.h
@@ -25,6 +25,10 @@
 class MutableDataBatch : public DataBatch {
  public:
   MutableDataBatch();
+
+  MutableDataBatch(const MutableDataBatch&) = delete;
+  MutableDataBatch& operator=(const MutableDataBatch&) = delete;
+
   ~MutableDataBatch() override;
 
   // Takes ownership of the data tied to a given key used for storage. Put
@@ -40,8 +44,6 @@
  private:
   std::vector<KeyAndData> key_data_pairs_;
   size_t read_index_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(MutableDataBatch);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/proxy_model_type_controller_delegate.h b/components/sync/model/proxy_model_type_controller_delegate.h
index 8146d27..67ee1c8 100644
--- a/components/sync/model/proxy_model_type_controller_delegate.h
+++ b/components/sync/model/proxy_model_type_controller_delegate.h
@@ -25,6 +25,12 @@
   ProxyModelTypeControllerDelegate(
       const scoped_refptr<base::SequencedTaskRunner>& task_runner,
       const DelegateProvider& delegate_provider);
+
+  ProxyModelTypeControllerDelegate(const ProxyModelTypeControllerDelegate&) =
+      delete;
+  ProxyModelTypeControllerDelegate& operator=(
+      const ProxyModelTypeControllerDelegate&) = delete;
+
   ~ProxyModelTypeControllerDelegate() override;
 
   // ModelTypeControllerDelegate implementation.
@@ -47,8 +53,6 @@
 
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
   const DelegateProvider delegate_provider_;
-
-  DISALLOW_COPY_AND_ASSIGN(ProxyModelTypeControllerDelegate);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/syncable_service.h b/components/sync/model/syncable_service.h
index 52ca5cdf..c224355 100644
--- a/components/sync/model/syncable_service.h
+++ b/components/sync/model/syncable_service.h
@@ -26,6 +26,10 @@
 class SyncableService : public base::SupportsWeakPtr<SyncableService> {
  public:
   SyncableService() = default;
+
+  SyncableService(const SyncableService&) = delete;
+  SyncableService& operator=(const SyncableService&) = delete;
+
   virtual ~SyncableService() = default;
 
   // A StartSyncFlare is useful when your SyncableService has a need for sync
@@ -71,9 +75,6 @@
   virtual absl::optional<ModelError> ProcessSyncChanges(
       const base::Location& from_here,
       const SyncChangeList& change_list) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(SyncableService);
 };
 
 }  // namespace syncer
diff --git a/components/sync/model/syncable_service_based_bridge.cc b/components/sync/model/syncable_service_based_bridge.cc
index 78deb819..f9a14de 100644
--- a/components/sync/model/syncable_service_based_bridge.cc
+++ b/components/sync/model/syncable_service_based_bridge.cc
@@ -118,6 +118,9 @@
     DCHECK(other);
   }
 
+  LocalChangeProcessor(const LocalChangeProcessor&) = delete;
+  LocalChangeProcessor& operator=(const LocalChangeProcessor&) = delete;
+
   ~LocalChangeProcessor() override {}
 
   absl::optional<ModelError> ProcessSyncChanges(
@@ -202,13 +205,15 @@
   SyncableServiceBasedBridge::InMemoryStore* const in_memory_store_;
   ModelTypeChangeProcessor* const other_;
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(LocalChangeProcessor);
 };
 
 class SyncErrorFactoryImpl : public SyncErrorFactory {
  public:
   explicit SyncErrorFactoryImpl(ModelType type) : type_(type) {}
+
+  SyncErrorFactoryImpl(const SyncErrorFactoryImpl&) = delete;
+  SyncErrorFactoryImpl& operator=(const SyncErrorFactoryImpl&) = delete;
+
   ~SyncErrorFactoryImpl() override = default;
 
   SyncError CreateAndUploadError(const base::Location& location,
@@ -219,8 +224,6 @@
 
  private:
   const ModelType type_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncErrorFactoryImpl);
 };
 
 }  // namespace
diff --git a/components/sync/model/syncable_service_based_bridge.h b/components/sync/model/syncable_service_based_bridge.h
index a42a461c..07a09851 100644
--- a/components/sync/model/syncable_service_based_bridge.h
+++ b/components/sync/model/syncable_service_based_bridge.h
@@ -44,6 +44,11 @@
       OnceModelTypeStoreFactory store_factory,
       std::unique_ptr<ModelTypeChangeProcessor> change_processor,
       SyncableService* syncable_service);
+
+  SyncableServiceBasedBridge(const SyncableServiceBasedBridge&) = delete;
+  SyncableServiceBasedBridge& operator=(const SyncableServiceBasedBridge&) =
+      delete;
+
   ~SyncableServiceBasedBridge() override;
 
   // ModelTypeSyncBridge implementation.
@@ -110,8 +115,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<SyncableServiceBasedBridge> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(SyncableServiceBasedBridge);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/keystore_keys_cryptographer.h b/components/sync/nigori/keystore_keys_cryptographer.h
index 05ad78d..a2e7dd4 100644
--- a/components/sync/nigori/keystore_keys_cryptographer.h
+++ b/components/sync/nigori/keystore_keys_cryptographer.h
@@ -32,6 +32,10 @@
   static std::unique_ptr<KeystoreKeysCryptographer> FromKeystoreKeys(
       const std::vector<std::string>& keystore_keys);
 
+  KeystoreKeysCryptographer(const KeystoreKeysCryptographer&) = delete;
+  KeystoreKeysCryptographer& operator=(const KeystoreKeysCryptographer&) =
+      delete;
+
   ~KeystoreKeysCryptographer();
 
   const std::vector<std::string>& keystore_keys() const {
@@ -70,8 +74,6 @@
 
   std::unique_ptr<CryptographerImpl> cryptographer_;
   std::vector<std::string> keystore_keys_;
-
-  DISALLOW_COPY_AND_ASSIGN(KeystoreKeysCryptographer);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_local_change_processor.h b/components/sync/nigori/nigori_local_change_processor.h
index ddd9402..9696358b 100644
--- a/components/sync/nigori/nigori_local_change_processor.h
+++ b/components/sync/nigori/nigori_local_change_processor.h
@@ -39,6 +39,10 @@
  public:
   NigoriLocalChangeProcessor() = default;
 
+  NigoriLocalChangeProcessor(const NigoriLocalChangeProcessor&) = delete;
+  NigoriLocalChangeProcessor& operator=(const NigoriLocalChangeProcessor&) =
+      delete;
+
   virtual ~NigoriLocalChangeProcessor() = default;
 
   // The Nigori model is expected to call this method as soon as possible during
@@ -74,9 +78,6 @@
   // false, and ModelReadyToSync() has already been called, then Put and Delete
   // will no-op and can be omitted by bridge.
   virtual bool IsTrackingMetadata() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NigoriLocalChangeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_model_type_processor.h b/components/sync/nigori/nigori_model_type_processor.h
index 0d07e07d..a59adc6b 100644
--- a/components/sync/nigori/nigori_model_type_processor.h
+++ b/components/sync/nigori/nigori_model_type_processor.h
@@ -25,6 +25,10 @@
                                  public NigoriLocalChangeProcessor {
  public:
   NigoriModelTypeProcessor();
+
+  NigoriModelTypeProcessor(const NigoriModelTypeProcessor&) = delete;
+  NigoriModelTypeProcessor& operator=(const NigoriModelTypeProcessor&) = delete;
+
   ~NigoriModelTypeProcessor() override;
 
   // ModelTypeProcessor implementation.
@@ -112,8 +116,6 @@
   // invalidated during destruction).
   base::WeakPtrFactory<ModelTypeControllerDelegate>
       weak_ptr_factory_for_controller_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(NigoriModelTypeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_storage.h b/components/sync/nigori/nigori_storage.h
index 802a4d9..c431327 100644
--- a/components/sync/nigori/nigori_storage.h
+++ b/components/sync/nigori/nigori_storage.h
@@ -15,6 +15,10 @@
 class NigoriStorage {
  public:
   NigoriStorage() = default;
+
+  NigoriStorage(const NigoriStorage&) = delete;
+  NigoriStorage& operator=(const NigoriStorage&) = delete;
+
   virtual ~NigoriStorage() = default;
 
   // Should atomically persist |data|.
@@ -26,9 +30,6 @@
 
   // Removes all previously stored data.
   virtual void ClearData() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NigoriStorage);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_storage_impl.h b/components/sync/nigori/nigori_storage_impl.h
index 0c95a9a9..e70a8db 100644
--- a/components/sync/nigori/nigori_storage_impl.h
+++ b/components/sync/nigori/nigori_storage_impl.h
@@ -15,6 +15,10 @@
  public:
   // |encryptor| must be not null and must outlive this object.
   explicit NigoriStorageImpl(const base::FilePath& path);
+
+  NigoriStorageImpl(const NigoriStorageImpl&) = delete;
+  NigoriStorageImpl& operator=(const NigoriStorageImpl&) = delete;
+
   ~NigoriStorageImpl() override;
 
   // NigoriStorage implementation.
@@ -27,7 +31,6 @@
   base::FilePath path_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-  DISALLOW_COPY_AND_ASSIGN(NigoriStorageImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_sync_bridge.h b/components/sync/nigori/nigori_sync_bridge.h
index 62ac8692..d085170c3 100644
--- a/components/sync/nigori/nigori_sync_bridge.h
+++ b/components/sync/nigori/nigori_sync_bridge.h
@@ -23,6 +23,9 @@
  public:
   NigoriSyncBridge() = default;
 
+  NigoriSyncBridge(const NigoriSyncBridge&) = delete;
+  NigoriSyncBridge& operator=(const NigoriSyncBridge&) = delete;
+
   virtual ~NigoriSyncBridge() = default;
 
   // Perform the initial merge between local and sync data.
@@ -39,9 +42,6 @@
   // Informs the bridge that sync has been disabed. The bridge is responsible
   // for deleting all data and metadata upon disabling sync.
   virtual void ApplyDisableSyncChanges() = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(NigoriSyncBridge);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc
index 21d2693..2ae02972 100644
--- a/components/sync/nigori/nigori_sync_bridge_impl.cc
+++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -332,6 +332,9 @@
       const base::RepeatingClosure& post_passphrase_accepted_cb)
       : post_passphrase_accepted_cb_(post_passphrase_accepted_cb) {}
 
+  BroadcastingObserver(const BroadcastingObserver&) = delete;
+  BroadcastingObserver& operator=(const BroadcastingObserver&) = delete;
+
   ~BroadcastingObserver() override = default;
 
   void AddObserver(SyncEncryptionHandler::Observer* observer) {
@@ -405,8 +408,6 @@
   base::ObserverList<SyncEncryptionHandler::Observer>::Unchecked observers_;
 
   const base::RepeatingClosure post_passphrase_accepted_cb_;
-
-  DISALLOW_COPY_AND_ASSIGN(BroadcastingObserver);
 };
 
 NigoriSyncBridgeImpl::NigoriSyncBridgeImpl(
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h
index e773afa..6eca8009 100644
--- a/components/sync/nigori/nigori_sync_bridge_impl.h
+++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -53,6 +53,10 @@
       std::unique_ptr<NigoriStorage> storage,
       const std::string& packed_explicit_passphrase_key,
       const std::string& packed_keystore_keys);
+
+  NigoriSyncBridgeImpl(const NigoriSyncBridgeImpl&) = delete;
+  NigoriSyncBridgeImpl& operator=(const NigoriSyncBridgeImpl&) = delete;
+
   ~NigoriSyncBridgeImpl() override;
 
   // SyncEncryptionHandler implementation.
@@ -189,8 +193,6 @@
   const std::unique_ptr<BroadcastingObserver> broadcasting_observer_;
 
   SEQUENCE_CHECKER(sequence_checker_);
-
-  DISALLOW_COPY_AND_ASSIGN(NigoriSyncBridgeImpl);
 };
 
 }  // namespace syncer
diff --git a/components/sync/nigori/pending_local_nigori_commit.cc b/components/sync/nigori/pending_local_nigori_commit.cc
index 6c29929..38f5ff8e 100644
--- a/components/sync/nigori/pending_local_nigori_commit.cc
+++ b/components/sync/nigori/pending_local_nigori_commit.cc
@@ -57,6 +57,9 @@
         key_derivation_params_(CreateKeyDerivationParamsForCustomPassphrase()) {
   }
 
+  CustomPassphraseSetter(const CustomPassphraseSetter&) = delete;
+  CustomPassphraseSetter& operator=(const CustomPassphraseSetter&) = delete;
+
   ~CustomPassphraseSetter() override = default;
 
   bool TryApply(NigoriState* state) const override {
@@ -122,13 +125,15 @@
  private:
   const std::string passphrase_;
   const KeyDerivationParams key_derivation_params_;
-
-  DISALLOW_COPY_AND_ASSIGN(CustomPassphraseSetter);
 };
 
 class KeystoreInitializer : public PendingLocalNigoriCommit {
  public:
   KeystoreInitializer() = default;
+
+  KeystoreInitializer(const KeystoreInitializer&) = delete;
+  KeystoreInitializer& operator=(const KeystoreInitializer&) = delete;
+
   ~KeystoreInitializer() override = default;
 
   bool TryApply(NigoriState* state) const override {
@@ -156,14 +161,15 @@
   }
 
   void OnFailure(SyncEncryptionHandler::Observer* observer) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(KeystoreInitializer);
 };
 
 class KeystoreReencryptor : public PendingLocalNigoriCommit {
  public:
   KeystoreReencryptor() = default;
+
+  KeystoreReencryptor(const KeystoreReencryptor&) = delete;
+  KeystoreReencryptor& operator=(const KeystoreReencryptor&) = delete;
+
   ~KeystoreReencryptor() override = default;
 
   bool TryApply(NigoriState* state) const override {
@@ -186,9 +192,6 @@
   }
 
   void OnFailure(SyncEncryptionHandler::Observer* observer) override {}
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(KeystoreReencryptor);
 };
 
 }  // namespace
diff --git a/components/sync/nigori/pending_local_nigori_commit.h b/components/sync/nigori/pending_local_nigori_commit.h
index b5ba3ea..d9e92a4 100644
--- a/components/sync/nigori/pending_local_nigori_commit.h
+++ b/components/sync/nigori/pending_local_nigori_commit.h
@@ -28,6 +28,10 @@
   static std::unique_ptr<PendingLocalNigoriCommit> ForKeystoreReencryption();
 
   PendingLocalNigoriCommit() = default;
+
+  PendingLocalNigoriCommit(const PendingLocalNigoriCommit&) = delete;
+  PendingLocalNigoriCommit& operator=(const PendingLocalNigoriCommit&) = delete;
+
   virtual ~PendingLocalNigoriCommit() = default;
 
   // Attempts to modify |*state| to reflect the intended commit. Returns true if
@@ -45,9 +49,6 @@
   // Invoked when the change no longer applies or was aborted for a different
   // reason (e.g. sync disabled). |observer| must not be null.
   virtual void OnFailure(SyncEncryptionHandler::Observer* observer) = 0;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(PendingLocalNigoriCommit);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/fake_sync_manager.h b/components/sync/test/engine/fake_sync_manager.h
index e582a67..11517c1a 100644
--- a/components/sync/test/engine/fake_sync_manager.h
+++ b/components/sync/test/engine/fake_sync_manager.h
@@ -44,6 +44,10 @@
   FakeSyncManager(ModelTypeSet initial_sync_ended_types,
                   ModelTypeSet progress_marker_types,
                   ModelTypeSet configure_fail_types);
+
+  FakeSyncManager(const FakeSyncManager&) = delete;
+  FakeSyncManager& operator=(const FakeSyncManager&) = delete;
+
   ~FakeSyncManager() override;
 
   // Returns those types that have been downloaded since the last call to
@@ -133,8 +137,6 @@
 
   // Number of invalidations received per type since startup.
   std::map<ModelType, int> num_invalidations_received_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeSyncManager);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/mock_model_type_processor.h b/components/sync/test/engine/mock_model_type_processor.h
index 71f904d..545cafe 100644
--- a/components/sync/test/engine/mock_model_type_processor.h
+++ b/components/sync/test/engine/mock_model_type_processor.h
@@ -38,6 +38,10 @@
   using DisconnectCallback = base::OnceCallback<void()>;
 
   MockModelTypeProcessor();
+
+  MockModelTypeProcessor(const MockModelTypeProcessor&) = delete;
+  MockModelTypeProcessor& operator=(const MockModelTypeProcessor&) = delete;
+
   ~MockModelTypeProcessor() override;
 
   // Implementation of ModelTypeProcessor.
@@ -183,8 +187,6 @@
   CommitRequestDataList commit_request_;
 
   int get_local_changes_call_count_ = 0;
-
-  DISALLOW_COPY_AND_ASSIGN(MockModelTypeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/mock_model_type_worker.h b/components/sync/test/engine/mock_model_type_worker.h
index 5cd793d..ce9f0247 100644
--- a/components/sync/test/engine/mock_model_type_worker.h
+++ b/components/sync/test/engine/mock_model_type_worker.h
@@ -39,6 +39,10 @@
  public:
   MockModelTypeWorker(const sync_pb::ModelTypeState& model_type_state,
                       ModelTypeProcessor* processor);
+
+  MockModelTypeWorker(const MockModelTypeWorker&) = delete;
+  MockModelTypeWorker& operator=(const MockModelTypeWorker&) = delete;
+
   ~MockModelTypeWorker() override;
 
   // Callback when local changes are received from the processor.
@@ -175,8 +179,6 @@
 
   // WeakPtrFactory for this worker which will be sent to sync thread.
   base::WeakPtrFactory<MockModelTypeWorker> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(MockModelTypeWorker);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/mock_nudge_handler.h b/components/sync/test/engine/mock_nudge_handler.h
index 6d0a57a..cff7b04 100644
--- a/components/sync/test/engine/mock_nudge_handler.h
+++ b/components/sync/test/engine/mock_nudge_handler.h
@@ -15,6 +15,10 @@
 class MockNudgeHandler : public NudgeHandler {
  public:
   MockNudgeHandler();
+
+  MockNudgeHandler(const MockNudgeHandler&) = delete;
+  MockNudgeHandler& operator=(const MockNudgeHandler&) = delete;
+
   ~MockNudgeHandler() override;
 
   void NudgeForInitialDownload(ModelType type) override;
@@ -28,8 +32,6 @@
  private:
   int num_initial_nudges_;
   int num_commit_nudges_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockNudgeHandler);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/engine/single_type_mock_server.h b/components/sync/test/engine/single_type_mock_server.h
index 6e7d3bf..a163d7f 100644
--- a/components/sync/test/engine/single_type_mock_server.h
+++ b/components/sync/test/engine/single_type_mock_server.h
@@ -39,6 +39,10 @@
 class SingleTypeMockServer {
  public:
   explicit SingleTypeMockServer(ModelType type);
+
+  SingleTypeMockServer(const SingleTypeMockServer&) = delete;
+  SingleTypeMockServer& operator=(const SingleTypeMockServer&) = delete;
+
   ~SingleTypeMockServer();
 
   // Generates a SyncEntity representing a server-delivered update containing
@@ -110,8 +114,6 @@
 
   // The token that is used to generate the current progress marker.
   std::string progress_marker_token_;
-
-  DISALLOW_COPY_AND_ASSIGN(SingleTypeMockServer);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/fake_server/fake_server_http_post_provider.h b/components/sync/test/fake_server/fake_server_http_post_provider.h
index 0f80c02..4c753d9 100644
--- a/components/sync/test/fake_server/fake_server_http_post_provider.h
+++ b/components/sync/test/fake_server/fake_server_http_post_provider.h
@@ -84,6 +84,12 @@
   FakeServerHttpPostProviderFactory(
       const base::WeakPtr<FakeServer>& fake_server,
       scoped_refptr<base::SequencedTaskRunner> fake_server_task_runner);
+
+  FakeServerHttpPostProviderFactory(const FakeServerHttpPostProviderFactory&) =
+      delete;
+  FakeServerHttpPostProviderFactory& operator=(
+      const FakeServerHttpPostProviderFactory&) = delete;
+
   ~FakeServerHttpPostProviderFactory() override;
 
   // HttpPostProviderFactory:
@@ -94,8 +100,6 @@
   // |fake_server_task_runner_| runs on.
   base::WeakPtr<FakeServer> fake_server_;
   scoped_refptr<base::SequencedTaskRunner> fake_server_task_runner_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeServerHttpPostProviderFactory);
 };
 
 }  // namespace fake_server
diff --git a/components/sync/test/fake_server/fake_server_verifier.h b/components/sync/test/fake_server/fake_server_verifier.h
index fc728cdc..42c3bcb 100644
--- a/components/sync/test/fake_server/fake_server_verifier.h
+++ b/components/sync/test/fake_server/fake_server_verifier.h
@@ -27,6 +27,10 @@
   // Creates a FakeServerVerifier for |fake_server|. This class does not take
   // ownership of |fake_server|.
   explicit FakeServerVerifier(FakeServer* fake_server);
+
+  FakeServerVerifier(const FakeServerVerifier&) = delete;
+  FakeServerVerifier& operator=(const FakeServerVerifier&) = delete;
+
   virtual ~FakeServerVerifier();
 
   // Returns a successful result if there are |expected_count| entities with the
@@ -51,8 +55,6 @@
 
  private:
   FakeServer* const fake_server_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeServerVerifier);
 };
 
 }  // namespace fake_server
diff --git a/components/sync/test/model/fake_model_type_controller_delegate.h b/components/sync/test/model/fake_model_type_controller_delegate.h
index 977eade..62bd517 100644
--- a/components/sync/test/model/fake_model_type_controller_delegate.h
+++ b/components/sync/test/model/fake_model_type_controller_delegate.h
@@ -19,6 +19,12 @@
 class FakeModelTypeControllerDelegate : public ModelTypeControllerDelegate {
  public:
   explicit FakeModelTypeControllerDelegate(ModelType type);
+
+  FakeModelTypeControllerDelegate(const FakeModelTypeControllerDelegate&) =
+      delete;
+  FakeModelTypeControllerDelegate& operator=(
+      const FakeModelTypeControllerDelegate&) = delete;
+
   ~FakeModelTypeControllerDelegate() override;
 
   void SetModelTypeStateForActivationResponse(
@@ -62,8 +68,6 @@
   StartCallback start_callback_;
   ModelErrorHandler error_handler_;
   base::WeakPtrFactory<FakeModelTypeControllerDelegate> weak_ptr_factory_{this};
-
-  DISALLOW_COPY_AND_ASSIGN(FakeModelTypeControllerDelegate);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/model/fake_sync_change_processor.h b/components/sync/test/model/fake_sync_change_processor.h
index 39fc42d..c05029c1 100644
--- a/components/sync/test/model/fake_sync_change_processor.h
+++ b/components/sync/test/model/fake_sync_change_processor.h
@@ -13,6 +13,10 @@
 class FakeSyncChangeProcessor : public SyncChangeProcessor {
  public:
   FakeSyncChangeProcessor();
+
+  FakeSyncChangeProcessor(const FakeSyncChangeProcessor&) = delete;
+  FakeSyncChangeProcessor& operator=(const FakeSyncChangeProcessor&) = delete;
+
   ~FakeSyncChangeProcessor() override;
 
   // SyncChangeProcessor implementation.
@@ -28,8 +32,6 @@
 
  private:
   SyncChangeList changes_;
-
-  DISALLOW_COPY_AND_ASSIGN(FakeSyncChangeProcessor);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/model/mock_model_type_change_processor.h b/components/sync/test/model/mock_model_type_change_processor.h
index a993a60..68bbdf7 100644
--- a/components/sync/test/model/mock_model_type_change_processor.h
+++ b/components/sync/test/model/mock_model_type_change_processor.h
@@ -18,6 +18,11 @@
 class MockModelTypeChangeProcessor : public ModelTypeChangeProcessor {
  public:
   MockModelTypeChangeProcessor();
+
+  MockModelTypeChangeProcessor(const MockModelTypeChangeProcessor&) = delete;
+  MockModelTypeChangeProcessor& operator=(const MockModelTypeChangeProcessor&) =
+      delete;
+
   ~MockModelTypeChangeProcessor() override;
   MOCK_METHOD(void,
               Put,
@@ -81,9 +86,6 @@
   // Delegates all calls to another instance. |delegate| must not be null and
   // must outlive this object.
   void DelegateCallsByDefaultTo(ModelTypeChangeProcessor* delegate);
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MockModelTypeChangeProcessor);
 };
 
 }  //  namespace syncer
diff --git a/components/sync/test/model/sync_change_processor_wrapper_for_test.h b/components/sync/test/model/sync_change_processor_wrapper_for_test.h
index 6b26f69..efc894ce 100644
--- a/components/sync/test/model/sync_change_processor_wrapper_for_test.h
+++ b/components/sync/test/model/sync_change_processor_wrapper_for_test.h
@@ -24,6 +24,12 @@
   explicit SyncChangeProcessorWrapperForTest(SyncChangeProcessor* wrapped);
   // Overload for SyncableService.
   explicit SyncChangeProcessorWrapperForTest(SyncableService* wrapped);
+
+  SyncChangeProcessorWrapperForTest(const SyncChangeProcessorWrapperForTest&) =
+      delete;
+  SyncChangeProcessorWrapperForTest& operator=(
+      const SyncChangeProcessorWrapperForTest&) = delete;
+
   ~SyncChangeProcessorWrapperForTest() override;
 
   // SyncChangeProcessor implementation.
@@ -36,8 +42,6 @@
       const base::Location& from_here,
       const SyncChangeList& change_list)>
       process_sync_changes_;
-
-  DISALLOW_COPY_AND_ASSIGN(SyncChangeProcessorWrapperForTest);
 };
 
 }  // namespace syncer
diff --git a/components/sync/test/model/test_model_type_store_service.h b/components/sync/test/model/test_model_type_store_service.h
index bd49b57..2832939b 100644
--- a/components/sync/test/model/test_model_type_store_service.h
+++ b/components/sync/test/model/test_model_type_store_service.h
@@ -20,6 +20,11 @@
 class TestModelTypeStoreService : public ModelTypeStoreService {
  public:
   TestModelTypeStoreService();
+
+  TestModelTypeStoreService(const TestModelTypeStoreService&) = delete;
+  TestModelTypeStoreService& operator=(const TestModelTypeStoreService&) =
+      delete;
+
   ~TestModelTypeStoreService() override;
 
   // ModelTypeStoreService:
@@ -30,8 +35,6 @@
  private:
   const scoped_refptr<ModelTypeStoreBackend> store_backend_;
   base::ScopedTempDir sync_data_path_;
-
-  DISALLOW_COPY_AND_ASSIGN(TestModelTypeStoreService);
 };
 
 }  // namespace syncer
diff --git a/components/version_info/version_info.cc b/components/version_info/version_info.cc
index 9f4b1f66..388f21cc 100644
--- a/components/version_info/version_info.cc
+++ b/components/version_info/version_info.cc
@@ -30,8 +30,8 @@
 }
 
 std::string GetMajorVersionNumber() {
-  DCHECK(version_info::GetVersion().IsValid());
-  return base::NumberToString(version_info::GetVersion().components()[0]);
+  DCHECK(GetVersion().IsValid());
+  return base::NumberToString(GetVersion().components()[0]);
 }
 
 const base::Version& GetVersion() {
diff --git a/components/viz/service/display_embedder/skia_output_device_offscreen.cc b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
index bc068b6c..4237369 100644
--- a/components/viz/service/display_embedder/skia_output_device_offscreen.cc
+++ b/components/viz/service/display_embedder/skia_output_device_offscreen.cc
@@ -107,10 +107,14 @@
 
   DCHECK(!backbuffer_estimated_size_);
   if (backend_texture_.backend() == GrBackendApi::kVulkan) {
+#if BUILDFLAG(ENABLE_VULKAN)
     GrVkImageInfo vk_image_info;
     bool result = backend_texture_.getVkImageInfo(&vk_image_info);
     DCHECK(result);
     backbuffer_estimated_size_ = vk_image_info.fAlloc.fSize;
+#else
+    DCHECK(false);
+#endif
   } else {
     auto info = SkImageInfo::Make(size_.width(), size_.height(),
                                   kSurfaceColorType, kUnpremul_SkAlphaType);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc
index 4a1b0f4..0c16740 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -924,7 +924,9 @@
         capabilities_.uses_default_gl_framebuffer, false /* isTextureable */,
         GrProtected::kNo, false /* vkRTSupportsInputAttachment */,
         capabilities_.root_is_vulkan_secondary_command_buffer);
+#if BUILDFLAG(ENABLE_VULKAN)
     VkFormat vk_format = VK_FORMAT_UNDEFINED;
+#endif
     LOG_IF(DFATAL, !characterization.isValid())
         << "\n  surface_size=" << surface_size.ToString()
         << "\n  format=" << static_cast<int>(format)
@@ -934,10 +936,12 @@
         << static_cast<int>(backend_format.backend())
         << "\n  backend_format.asGLFormat()="
         << static_cast<int>(backend_format.asGLFormat())
+#if BUILDFLAG(ENABLE_VULKAN)
         << "\n  backend_format.asVkFormat()="
         << static_cast<int>(backend_format.asVkFormat(&vk_format))
         << "\n  backend_format.asVkFormat() vk_format="
         << static_cast<int>(vk_format)
+#endif
         << "\n  surface_origin=" << static_cast<int>(surface_origin)
         << "\n  willGlFBO0=" << capabilities_.uses_default_gl_framebuffer;
     return characterization;
diff --git a/components/webapps/browser/installable/installable_manager.cc b/components/webapps/browser/installable/installable_manager.cc
index b1381ed..2dc079e 100644
--- a/components/webapps/browser/installable/installable_manager.cc
+++ b/components/webapps/browser/installable/installable_manager.cc
@@ -723,11 +723,6 @@
 void InstallableManager::CheckServiceWorker() {
   DCHECK(!worker_->fetched);
   DCHECK(!blink::IsEmptyManifest(manifest()));
-  // Service workers need a StorageKey (storage partitioning key), since we only
-  // install for top-level frames we can assume the StorageKey will always be in
-  // a 1P context. DCHECK this just to be sure.
-  DCHECK(GetWebContents() &&
-         GetWebContents()->GetMainFrame()->GetParent() == nullptr);
 
   if (!service_worker_context_)
     return;
diff --git a/content/browser/appcache/appcache_cache_test_helper.cc b/content/browser/appcache/appcache_cache_test_helper.cc
deleted file mode 100644
index 6cae91b4..0000000
--- a/content/browser/appcache/appcache_cache_test_helper.cc
+++ /dev/null
@@ -1,237 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_cache_test_helper.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_response_headers.h"
-
-namespace content {
-
-namespace {
-const int kAppCacheFetchBufferSize = 32768;
-}  // namespace
-
-AppCacheCacheTestHelper::CacheEntry::CacheEntry(
-    int types,
-    std::string expect_if_modified_since,
-    std::string expect_if_none_match,
-    bool headers_allowed,
-    std::unique_ptr<net::HttpResponseInfo> response_info,
-    const std::string& body)
-    : types(types),
-      expect_if_modified_since(expect_if_modified_since),
-      expect_if_none_match(expect_if_none_match),
-      headers_allowed(headers_allowed),
-      response_info(std::move(response_info)),
-      body(body) {}
-
-AppCacheCacheTestHelper::CacheEntry::~CacheEntry() = default;
-
-// static
-void AppCacheCacheTestHelper::AddCacheEntry(
-    CacheEntries* cache_entries,
-    const GURL& url,
-    int types,
-    std::string expect_if_modified_since,
-    std::string expect_if_none_match,
-    bool headers_allowed,
-    std::unique_ptr<net::HttpResponseInfo> response_info,
-    const std::string& body) {
-  cache_entries->emplace(
-      url, std::make_unique<AppCacheCacheTestHelper::CacheEntry>(
-               types, expect_if_modified_since, expect_if_none_match,
-               headers_allowed, std::move(response_info), body));
-}
-
-AppCacheCacheTestHelper::AppCacheCacheTestHelper(
-    const MockAppCacheService* service,
-    const GURL& manifest_url,
-    AppCache* const cache,
-    CacheEntries cache_entries,
-    base::OnceCallback<void(int)> post_write_callback)
-    : service_(service),
-      manifest_url_(manifest_url),
-      cache_(cache),
-      cache_entries_(std::move(cache_entries)),
-      state_(State::kIdle),
-      post_write_callback_(std::move(post_write_callback)) {}
-
-AppCacheCacheTestHelper::~AppCacheCacheTestHelper() = default;
-
-void AppCacheCacheTestHelper::PrepareForRead(
-    AppCache* read_cache,
-    base::OnceClosure post_read_callback) {
-  read_cache_ = read_cache;
-  post_read_callback_ = std::move(post_read_callback);
-}
-
-void AppCacheCacheTestHelper::Read() {
-  DCHECK_EQ(state_, State::kIdle);
-  state_ = State::kReadInfo;
-  read_it_ = read_cache_->entries().begin();
-  read_cache_entries_.clear();
-  AsyncRead(0);
-}
-
-void AppCacheCacheTestHelper::Write() {
-  DCHECK_EQ(state_, State::kIdle);
-  state_ = State::kWriteInfo;
-  write_it_ = cache_entries_.begin();
-  AsyncWrite(0);
-}
-
-void AppCacheCacheTestHelper::OnResponseInfoLoaded(
-    AppCacheResponseInfo* response_info,
-    int64_t response_id) {
-  DCHECK(response_info);
-  DCHECK_EQ(read_entry_response_id_, response_id);
-
-  read_info_response_info_.reset();
-  read_info_response_info_ = response_info;
-  AsyncRead(0);
-}
-
-void AppCacheCacheTestHelper::AsyncRead(int result) {
-  DCHECK(state_ == State::kReadInfo || state_ == State::kReadData);
-  DCHECK_GE(result, 0);
-  if (read_it_ == read_cache_->entries().end()) {
-    state_ = State::kIdle;
-    std::move(post_read_callback_).Run();
-    return;
-  }
-  switch (state_) {
-    case State::kReadInfo: {
-      if (!read_info_response_info_) {
-        AppCacheEntry* entry = read_cache_->GetEntry(read_it_->first);
-        DCHECK(entry);
-        read_entry_response_id_ = entry->response_id();
-        service_->storage()->LoadResponseInfo(manifest_url_,
-                                              read_entry_response_id_, this);
-      } else {
-        // Result is in |read_info_response_info_|.  Keep it there for now.
-        // Will be passed along after data is read.
-
-        // Prepare for next state.
-        state_ = State::kReadData;
-
-        // Trigger data read for |read_entry_response_id_|.
-        read_data_response_reader_ = service_->storage()->CreateResponseReader(
-            read_it_->first, read_entry_response_id_);
-        read_data_buffer_ =
-            base::MakeRefCounted<net::IOBuffer>(kAppCacheFetchBufferSize);
-        read_data_response_reader_->ReadData(
-            read_data_buffer_.get(), kAppCacheFetchBufferSize,
-            base::BindOnce(&AppCacheCacheTestHelper::AsyncRead,
-                           base::Unretained(this)));
-      }
-    } break;
-    case State::kReadData: {
-      if (result > 0) {
-        read_data_loaded_data_.append(read_data_buffer_->data(), result);
-        read_data_response_reader_->ReadData(
-            read_data_buffer_.get(), kAppCacheFetchBufferSize,
-            base::BindOnce(&AppCacheCacheTestHelper::AsyncRead,
-                           base::Unretained(this)));
-      } else {
-        // Result is in |read_data_loaded_data_|.
-
-        std::unique_ptr<net::HttpResponseInfo> http_response_info =
-            std::make_unique<net::HttpResponseInfo>(
-                read_info_response_info_->http_response_info());
-        AppCacheCacheTestHelper::AddCacheEntry(
-            &read_cache_entries_, read_it_->first, AppCacheEntry::EXPLICIT,
-            /*expect_if_modified_since=*/std::string(),
-            /*expect_if_none_match=*/std::string(), /*headers_allowed=*/false,
-            std::move(http_response_info), read_data_loaded_data_);
-
-        // Reset after read.
-        read_info_response_info_.reset();
-        read_entry_response_id_ = 0;
-        read_data_buffer_.reset();
-        read_data_loaded_data_ = "";
-        read_data_response_reader_.reset();
-
-        // Prepare for next state.
-        state_ = State::kReadInfo;
-        read_it_++;  // move to next entry
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE, base::BindOnce(&AppCacheCacheTestHelper::AsyncRead,
-                                      base::Unretained(this), 0));
-      }
-    } break;
-    default:
-      NOTREACHED();
-      break;
-  }
-}
-
-void AppCacheCacheTestHelper::AsyncWrite(int result) {
-  DCHECK(state_ == State::kWriteInfo || state_ == State::kWriteData);
-  DCHECK_GE(result, 0);
-  if (write_it_ == cache_entries_.end()) {
-    state_ = State::kIdle;
-    std::move(post_write_callback_).Run(1);
-    return;
-  }
-  switch (state_) {
-    case State::kWriteInfo: {
-      // Prepare for info write.
-      response_writer_.reset();
-      response_writer_ =
-          service_->storage()->CreateResponseWriter(manifest_url_);
-      AppCacheEntry* entry = cache_->GetEntry(write_it_->first);
-      if (entry) {
-        entry->add_types(write_it_->second->types);
-        entry->set_response_id(response_writer_->response_id());
-      } else {
-        cache_->AddEntry(write_it_->first,
-                         AppCacheEntry(write_it_->second->types,
-                                       response_writer_->response_id()));
-      }
-      // Copy |response_info| so later calls can access the original response
-      // info.
-      std::unique_ptr<net::HttpResponseInfo> http_response_info =
-          std::make_unique<net::HttpResponseInfo>(
-              *(write_it_->second->response_info));
-      scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-          base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-              std::move(http_response_info));
-
-      // Prepare for next state.
-      state_ = State::kWriteData;
-
-      // Trigger async WriteInfo() call.
-      response_writer_->WriteInfo(
-          io_buffer.get(), base::BindOnce(&AppCacheCacheTestHelper::AsyncWrite,
-                                          base::Unretained(this)));
-    } break;
-    case State::kWriteData: {
-      // Prepare for data write.
-      std::string body = write_it_->second->body;
-      scoped_refptr<net::StringIOBuffer> io_buffer =
-          base::MakeRefCounted<net::StringIOBuffer>(body);
-
-      // Prepare for next state.
-      state_ = State::kWriteInfo;
-      write_it_++;  // move to next entry
-
-      // Trigger async WriteData() call.
-      response_writer_->WriteData(
-          io_buffer.get(), body.length(),
-          base::BindOnce(&AppCacheCacheTestHelper::AsyncWrite,
-                         base::Unretained(this)));
-    } break;
-    default:
-      NOTREACHED();
-      break;
-  }
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_cache_test_helper.h b/content/browser/appcache/appcache_cache_test_helper.h
deleted file mode 100644
index 57a20df..0000000
--- a/content/browser/appcache/appcache_cache_test_helper.h
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_APPCACHE_APPCACHE_CACHE_TEST_HELPER_H_
-#define CONTENT_BROWSER_APPCACHE_APPCACHE_CACHE_TEST_HELPER_H_
-
-#include "content/browser/appcache/mock_appcache_service.h"
-
-namespace content {
-
-// Helper class to read cache info from and write cache info to disk.
-class AppCacheCacheTestHelper : public AppCacheStorage::Delegate {
- public:
-  // Helpers to collect cache entry information in a single location.
-  struct CacheEntry {
-    CacheEntry(int types,
-               std::string expect_if_modified_since,
-               std::string expect_if_none_match,
-               bool headers_allowed,
-               std::unique_ptr<net::HttpResponseInfo> response_info,
-               const std::string& body);
-    ~CacheEntry();
-
-    int types;  // The combination of AppCacheEntry::Type values for this entry.
-    std::string expect_if_modified_since;
-    std::string expect_if_none_match;
-    bool headers_allowed = true;
-    std::unique_ptr<net::HttpResponseInfo> response_info;
-    std::string body;
-  };
-
-  using CacheEntries = std::map<GURL, std::unique_ptr<CacheEntry>>;
-
-  static void AddCacheEntry(
-      CacheEntries* cache_entries,
-      const GURL& url,
-      int types,
-      std::string expect_if_modified_since,
-      std::string expect_if_none_match,
-      bool headers_allowed,
-      std::unique_ptr<net::HttpResponseInfo> response_info,
-      const std::string& body);
-
-  AppCacheCacheTestHelper(const MockAppCacheService* service,
-                          const GURL& manifest_url,
-                          AppCache* const cache,
-                          CacheEntries cache_entries,
-                          base::OnceCallback<void(int)> post_write_callback);
-  ~AppCacheCacheTestHelper() override;
-
-  AppCache* write_cache() { return cache_; }
-  const CacheEntries& cache_entries() { return cache_entries_; }
-  const CacheEntries& read_cache_entries() { return read_cache_entries_; }
-
-  void PrepareForRead(AppCache* cache, base::OnceClosure post_read_callback);
-  void Read();
-  void Write();
-  void OnResponseInfoLoaded(AppCacheResponseInfo* response_info,
-                            int64_t response_id) override;
-
- private:
-  enum class State {
-    kIdle,
-    kReadInfo,
-    kReadData,
-    kWriteInfo,
-    kWriteData,
-  };
-
-  void AsyncRead(int result);
-  void AsyncWrite(int result);
-
-  const MockAppCacheService* const service_;
-  const GURL manifest_url_;
-  AppCache* const cache_;
-  CacheEntries cache_entries_;
-  State state_;
-
-  // Used for writing cache info and data.
-  CacheEntries::const_iterator write_it_;
-  std::unique_ptr<AppCacheResponseWriter> response_writer_;
-  base::OnceCallback<void(int)> post_write_callback_;
-
-  // Used for reading cache info and data.
-  AppCache* read_cache_;
-  AppCache::EntryMap::const_iterator read_it_;
-  int64_t read_entry_response_id_;
-  scoped_refptr<AppCacheResponseInfo> read_info_response_info_;
-  scoped_refptr<net::IOBuffer> read_data_buffer_;
-  std::string read_data_loaded_data_;
-  std::unique_ptr<AppCacheResponseReader> read_data_response_reader_;
-  CacheEntries read_cache_entries_;
-  base::OnceClosure post_read_callback_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_CACHE_TEST_HELPER_H_
diff --git a/content/browser/appcache/appcache_cache_test_helper_unittest.cc b/content/browser/appcache/appcache_cache_test_helper_unittest.cc
deleted file mode 100644
index 288fa52..0000000
--- a/content/browser/appcache/appcache_cache_test_helper_unittest.cc
+++ /dev/null
@@ -1,419 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_cache_test_helper.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/cxx17_backports.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_host.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/appcache_update_job.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-
-namespace content {
-namespace appcache_cache_test_helper_unittest {
-
-class AppCacheCacheTestHelperTest;
-
-// Values should match values used in appcache_update_job.cc.
-const base::TimeDelta kOneHour = base::TimeDelta::FromHours(1);
-
-const char kManifest1Contents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "NETWORK:\n"
-    "*\n";
-
-// There are a handful of http accessible resources that we need to conduct
-// these tests. Instead of running a separate server to host these resources,
-// we mock them up.
-class MockHttpServer {
- public:
-  static GURL GetMockUrl(const std::string& path) {
-    return GURL("http://mockhost/" + path);
-  }
-
-  static void GetMockResponse(const std::string& path,
-                              std::string* headers,
-                              std::string* body) {
-    const char not_found_headers[] =
-        "HTTP/1.1 404 NOT FOUND\n"
-        "\n";
-    (*headers) = std::string(not_found_headers, base::size(not_found_headers));
-    (*body) = "";
-  }
-};
-
-inline bool operator==(const AppCacheNamespace& lhs,
-                       const AppCacheNamespace& rhs) {
-  return lhs.type == rhs.type && lhs.namespace_url == rhs.namespace_url &&
-         lhs.target_url == rhs.target_url;
-}
-
-class MockFrontend : public blink::mojom::AppCacheFrontend {
- public:
-  MockFrontend()
-      : ignore_progress_events_(false),
-        verify_progress_events_(false),
-        last_progress_total_(-1),
-        last_progress_complete_(-1),
-        start_update_trigger_(
-            blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT),
-        update_(nullptr) {}
-
-  void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {}
-
-  void EventRaised(blink::mojom::AppCacheEventID event_id) override {
-    raised_events_.push_back(event_id);
-
-    // Trigger additional updates if requested.
-    if (event_id == start_update_trigger_ && update_) {
-      for (AppCacheHost* host : update_hosts_) {
-        update_->StartUpdate(
-            host, (host ? host->pending_master_entry_url() : GURL()));
-      }
-      update_hosts_.clear();  // only trigger once
-    }
-  }
-
-  void ErrorEventRaised(
-      blink::mojom::AppCacheErrorDetailsPtr details) override {
-    error_message_ = details->message;
-    EventRaised(blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-  }
-
-  void ProgressEventRaised(const GURL& url,
-                           int32_t num_total,
-                           int32_t num_complete) override {
-    if (!ignore_progress_events_)
-      EventRaised(blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-
-    if (verify_progress_events_) {
-      EXPECT_GE(num_total, num_complete);
-      EXPECT_GE(num_complete, 0);
-
-      if (last_progress_total_ == -1) {
-        // Should start at zero.
-        EXPECT_EQ(0, num_complete);
-      } else {
-        // Total should be stable and complete should bump up by one at a time.
-        EXPECT_EQ(last_progress_total_, num_total);
-        EXPECT_EQ(last_progress_complete_ + 1, num_complete);
-      }
-
-      // Url should be valid for all except the 'final' event.
-      if (num_total == num_complete)
-        EXPECT_TRUE(url.is_empty());
-      else
-        EXPECT_TRUE(url.is_valid());
-
-      last_progress_total_ = num_total;
-      last_progress_complete_ = num_complete;
-    }
-  }
-
-  void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
-                  const std::string& message) override {}
-
-  void SetSubresourceFactory(
-      mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory)
-      override {}
-
-  void AddExpectedEvent(blink::mojom::AppCacheEventID event_id) {
-    DCHECK(!ignore_progress_events_ ||
-           event_id != blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    expected_events_.push_back(event_id);
-  }
-
-  void SetIgnoreProgressEvents(bool ignore) {
-    // Some tests involve joining new hosts to an already running update job
-    // or intentionally failing. The timing and sequencing of the progress
-    // events generated by an update job are dependent on the behavior of
-    // an external HTTP server. For jobs that do not run fully till completion,
-    // due to either joining late or early exit, we skip monitoring the
-    // progress events to avoid flakiness.
-    ignore_progress_events_ = ignore;
-  }
-
-  void SetVerifyProgressEvents(bool verify) {
-    verify_progress_events_ = verify;
-  }
-
-  void TriggerAdditionalUpdates(blink::mojom::AppCacheEventID trigger_event,
-                                AppCacheUpdateJob* update) {
-    start_update_trigger_ = trigger_event;
-    update_ = update;
-  }
-
-  void AdditionalUpdateHost(AppCacheHost* host) {
-    update_hosts_.push_back(host);
-  }
-
-  using RaisedEvents = std::vector<blink::mojom::AppCacheEventID>;
-  RaisedEvents raised_events_;
-  std::string error_message_;
-
-  // Set the expected events if verification needs to happen asynchronously.
-  RaisedEvents expected_events_;
-  std::string expected_error_message_;
-
-  bool ignore_progress_events_;
-
-  bool verify_progress_events_;
-  int last_progress_total_;
-  int last_progress_complete_;
-
-  // Add ability for frontend to add master entries to an inprogress update.
-  blink::mojom::AppCacheEventID start_update_trigger_;
-  AppCacheUpdateJob* update_;
-  std::vector<AppCacheHost*> update_hosts_;
-};
-
-class AppCacheCacheTestHelperTest : public testing::Test {
- public:
-  AppCacheCacheTestHelperTest()
-      : process_id_(123),
-        weak_partition_factory_(static_cast<StoragePartitionImpl*>(
-            browser_context_.GetDefaultStoragePartition())) {}
-
-  void SetUp() override {
-    ChildProcessSecurityPolicyImpl::GetInstance()->Add(process_id_,
-                                                       &browser_context_);
-  }
-
-  void TearDown() override {
-    ChildProcessSecurityPolicyImpl::GetInstance()->Remove(process_id_);
-  }
-  // Use a separate IO thread to run a test. Thread will be destroyed
-  // when it goes out of scope.
-  template <class Method>
-  void RunTestOnUIThread(Method method) {
-    base::RunLoop run_loop;
-    test_completed_cb_ = run_loop.QuitClosure();
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE, base::BindOnce(method, base::Unretained(this)));
-    run_loop.Run();
-  }
-
-  void BasicStart() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-
-    // Create a cache without a manifest entry.  The manifest entry will be
-    // added later.
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), -1);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    AppCacheCacheTestHelper::CacheEntries cache_entries;
-
-    // Add cache entry for manifest.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = std::move(headers);
-    AppCacheCacheTestHelper::AddCacheEntry(
-        &cache_entries, group_->manifest_url(), AppCacheEntry::EXPLICIT,
-        /*expect_if_modified_since=*/"Sat, 29 Oct 1994 19:43:31 GMT",
-        /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-        std::move(response_info), kManifest1Contents);
-
-    cache_helper_ = std::make_unique<AppCacheCacheTestHelper>(
-        service_.get(), group_->manifest_url(), cache, std::move(cache_entries),
-        base::BindOnce(&AppCacheCacheTestHelperTest::BasicWriteFinished,
-                       base::Unretained(this)));
-    cache_helper_->Write();
-    // Continues async in |BasicWriteFinished|.
-  }
-
-  void BasicWriteFinished(int result) {
-    cache_helper_->PrepareForRead(
-        group_->newest_complete_cache(),
-        base::BindOnce(&AppCacheCacheTestHelperTest::BasicReadFinished,
-                       base::Unretained(this)));
-    cache_helper_->Read();
-    // Continues async in |BasicReadFinished|.
-  }
-
-  void BasicReadFinished() {
-    EXPECT_EQ(cache_helper_->cache_entries().size(),
-              cache_helper_->read_cache_entries().size());
-    for (auto it = cache_helper_->cache_entries().begin();
-         it != cache_helper_->cache_entries().end(); ++it) {
-      auto read_it = cache_helper_->read_cache_entries().find(it->first);
-
-      EXPECT_EQ(it->second->response_info->headers->raw_headers(),
-                read_it->second->response_info->headers->raw_headers());
-
-      EXPECT_EQ(it->second->body, read_it->second->body);
-    }
-
-    Finished();
-  }
-
-  void Finished() {
-    // We unwind the stack prior to finishing up to let stack-based objects
-    // get deleted.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&AppCacheCacheTestHelperTest::FinishedUnwound,
-                                  base::Unretained(this)));
-  }
-
-  void FinishedUnwound() {
-    // Clean up everything that was created on the IO thread.
-    cache_helper_.reset();
-    protect_newest_cache_ = nullptr;
-    group_ = nullptr;
-    hosts_.clear();
-    frontends_.clear();
-    response_infos_.clear();
-    service_.reset(nullptr);
-
-    std::move(test_completed_cb_).Run();
-  }
-
-  void MakeService() {
-    service_ = std::make_unique<MockAppCacheService>(
-        weak_partition_factory_.GetWeakPtr());
-  }
-
-  AppCache* MakeCacheForGroup(int64_t cache_id, int64_t manifest_response_id) {
-    return MakeCacheForGroup(cache_id, group_->manifest_url(),
-                             manifest_response_id);
-  }
-
-  AppCache* MakeCacheForGroup(int64_t cache_id,
-                              const GURL& manifest_entry_url,
-                              int64_t manifest_response_id) {
-    AppCache* cache = new AppCache(service_->storage(), cache_id);
-    cache->set_complete(true);
-    cache->set_manifest_parser_version(1);
-    cache->set_manifest_scope("/");
-    cache->set_update_time(base::Time::Now() - kOneHour);
-    group_->AddCache(cache);
-    group_->set_last_full_update_check_time(cache->update_time());
-
-    // Add manifest entry to cache.
-    if (manifest_response_id >= 0) {
-      cache->AddEntry(manifest_entry_url, AppCacheEntry(AppCacheEntry::MANIFEST,
-                                                        manifest_response_id));
-    }
-
-    // Specific tests that expect a newer time should set
-    // expect_full_update_time_newer_than_ which causes this
-    // equality expectation to be ignored.
-    expect_full_update_time_equal_to_ = cache->update_time();
-
-    return cache;
-  }
-
-  AppCacheHost* MakeHost(blink::mojom::AppCacheFrontend* frontend) {
-    constexpr int kRenderFrameIdForTests = 456;
-    hosts_.push_back(std::make_unique<AppCacheHost>(
-        base::UnguessableToken::Create(), process_id_, kRenderFrameIdForTests,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            process_id_),
-        mojo::NullRemote(), service_.get()));
-    hosts_.back()->set_frontend_for_testing(frontend);
-    return hosts_.back().get();
-  }
-
-  AppCacheResponseInfo* MakeAppCacheResponseInfo(
-      const GURL& manifest_url,
-      int64_t response_id,
-      const std::string& raw_headers) {
-    std::unique_ptr<net::HttpResponseInfo> http_info =
-        std::make_unique<net::HttpResponseInfo>();
-    http_info->headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
-    auto info = base::MakeRefCounted<AppCacheResponseInfo>(
-        service_->storage()->GetWeakPtr(), manifest_url, response_id,
-        std::move(http_info), 0);
-    response_infos_.emplace_back(info);
-    return info.get();
-  }
-
-  MockFrontend* MakeMockFrontend() {
-    frontends_.push_back(std::make_unique<MockFrontend>());
-    return frontends_.back().get();
-  }
-
- private:
-  content::BrowserTaskEnvironment task_environment_;
-
-  std::unique_ptr<MockAppCacheService> service_;
-  scoped_refptr<AppCacheGroup> group_;
-  scoped_refptr<AppCache> protect_newest_cache_;
-  base::OnceClosure test_completed_cb_;
-
-  std::unique_ptr<AppCacheResponseWriter> response_writer_;
-  std::unique_ptr<AppCacheCacheTestHelper> cache_helper_;
-
-  // Hosts used by an async test that need to live until update job finishes.
-  // Otherwise, test can put host on the stack instead of here.
-  std::vector<std::unique_ptr<AppCacheHost>> hosts_;
-
-  // Response infos used by an async test that need to live until update job
-  // finishes.
-  std::vector<scoped_refptr<AppCacheResponseInfo>> response_infos_;
-
-  // Flag indicating if test cares to verify the update after update finishes.
-  base::Time expect_full_update_time_equal_to_;
-  std::vector<std::unique_ptr<MockFrontend>>
-      frontends_;  // to check expected events
-  AppCache::EntryMap expect_extra_entries_;
-  std::map<GURL, int64_t> expect_response_ids_;
-
-  content::TestBrowserContext browser_context_;
-  const int process_id_;
-  base::WeakPtrFactory<StoragePartitionImpl> weak_partition_factory_;
-};
-
-TEST_F(AppCacheCacheTestHelperTest, Basic) {
-  RunTestOnUIThread(&AppCacheCacheTestHelperTest::BasicStart);
-}
-
-}  // namespace appcache_cache_test_helper_unittest
-}  // namespace content
diff --git a/content/browser/appcache/appcache_database_unittest.cc b/content/browser/appcache/appcache_database_unittest.cc
deleted file mode 100644
index 0393a4dd..0000000
--- a/content/browser/appcache/appcache_database_unittest.cc
+++ /dev/null
@@ -1,1195 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/test/scoped_feature_list.h"
-#include "content/browser/appcache/appcache_database.h"
-#include "content/browser/appcache/appcache_entry.h"
-#include "sql/database.h"
-#include "sql/meta_table.h"
-#include "sql/statement.h"
-#include "sql/test/scoped_error_expecter.h"
-#include "sql/test/test_helpers.h"
-#include "sql/transaction.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/sqlite/sqlite3.h"
-
-namespace {
-
-const base::Time kZeroTime;
-
-}  // namespace
-
-namespace content {
-
-class AppCacheDatabaseTest : public testing::Test {
- public:
-  AppCacheDatabaseTest() {
-    appcache_require_origin_trial_feature_.InitAndDisableFeature(
-        blink::features::kAppCacheRequireOriginTrial);
-  }
-
-  int64_t GetCacheManifestParserVersion(const content::AppCacheDatabase& db,
-                                        int64_t cache_id) {
-    static const char kSql[] =
-        "SELECT manifest_parser_version, cache_id FROM Caches "
-        "WHERE "
-        "cache_id = ?";
-    sql::Statement statement(db.db_->GetCachedStatement(SQL_FROM_HERE, kSql));
-    statement.BindInt64(0, cache_id);
-    EXPECT_TRUE(statement.Step());
-    return statement.ColumnInt64(0);
-  }
-
-  std::string GetCacheManifestScope(const content::AppCacheDatabase& db,
-                                    int64_t cache_id) {
-    static const char kSql[] =
-        "SELECT manifest_scope, cache_id FROM Caches "
-        "WHERE "
-        "cache_id = ?";
-    sql::Statement statement(db.db_->GetCachedStatement(SQL_FROM_HERE, kSql));
-    statement.BindInt64(0, cache_id);
-    EXPECT_TRUE(statement.Step());
-    return statement.ColumnString(0);
-  }
-
- private:
-  base::test::ScopedFeatureList appcache_require_origin_trial_feature_;
-};
-
-TEST_F(AppCacheDatabaseTest, LazyOpen) {
-  // Use an empty file path to use an in-memory sqlite database.
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-
-  EXPECT_FALSE(db.LazyOpen(false));
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  int64_t group_id, cache_id, response_id, deleteable_response_rowid;
-  group_id = cache_id = response_id = deleteable_response_rowid = 0;
-  EXPECT_TRUE(db.FindLastStorageIds(&group_id, &cache_id, &response_id,
-                                    &deleteable_response_rowid));
-  EXPECT_EQ(0, group_id);
-  EXPECT_EQ(0, cache_id);
-  EXPECT_EQ(0, response_id);
-  EXPECT_EQ(0, deleteable_response_rowid);
-
-  std::set<url::Origin> origins;
-  EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
-  EXPECT_TRUE(origins.empty());
-}
-
-TEST_F(AppCacheDatabaseTest, ReCreate) {
-  // Real files on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile = temp_dir.GetPath().AppendASCII("appcache.db");
-  const base::FilePath kNestedDir = temp_dir.GetPath().AppendASCII("nested");
-  const base::FilePath kOtherFile =  kNestedDir.AppendASCII("other_file");
-  EXPECT_TRUE(base::CreateDirectory(kNestedDir));
-  EXPECT_TRUE(base::WriteFile(kOtherFile, "foo"));
-
-  AppCacheDatabase db(kDbFile);
-  EXPECT_FALSE(db.LazyOpen(false));
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  EXPECT_TRUE(base::PathExists(kDbFile));
-  EXPECT_TRUE(base::DirectoryExists(kNestedDir));
-  EXPECT_TRUE(base::PathExists(kOtherFile));
-
-  EXPECT_TRUE(db.DeleteExistingAndCreateNewDatabase());
-
-  EXPECT_TRUE(base::PathExists(kDbFile));
-  EXPECT_FALSE(base::DirectoryExists(kNestedDir));
-  EXPECT_FALSE(base::PathExists(kOtherFile));
-}
-
-#ifdef NDEBUG
-// Only run in release builds because sql::Database and familiy
-// crank up DLOG(FATAL)'ness and this test presents it with
-// intentionally bad data which causes debug builds to exit instead
-// of run to completion. In release builds, errors the are delivered
-// to the consumer so  we can test the error handling of the consumer.
-// TODO: crbug/328576
-TEST_F(AppCacheDatabaseTest, QuickIntegrityCheck) {
-  // Real files on disk for this test too, a corrupt database file.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  base::FilePath mock_dir = temp_dir.GetPath().AppendASCII("mock");
-  ASSERT_TRUE(base::CreateDirectory(mock_dir));
-
-  const base::FilePath kDbFile = mock_dir.AppendASCII("appcache.db");
-  const base::FilePath kOtherFile = mock_dir.AppendASCII("other_file");
-  EXPECT_TRUE(base::WriteFile(kOtherFile, "foo"));
-
-  // First create a valid db file.
-  {
-    AppCacheDatabase db(kDbFile);
-    EXPECT_TRUE(db.LazyOpen(true));
-    EXPECT_TRUE(base::PathExists(kOtherFile));
-    EXPECT_TRUE(base::PathExists(kDbFile));
-  }
-
-  // Break it.
-  ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
-
-  // Reopening will notice the corruption and delete/recreate the directory.
-  {
-    sql::test::ScopedErrorExpecter expecter;
-    expecter.ExpectError(SQLITE_CORRUPT);
-    AppCacheDatabase db(kDbFile);
-    EXPECT_TRUE(db.LazyOpen(true));
-    EXPECT_FALSE(base::PathExists(kOtherFile));
-    EXPECT_TRUE(base::PathExists(kDbFile));
-    EXPECT_TRUE(expecter.SawExpectedErrors());
-  }
-}
-#endif  // NDEBUG
-
-TEST_F(AppCacheDatabaseTest, WasCorrutionDetected) {
-  // Real files on disk for this test too, a corrupt database file.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile = temp_dir.GetPath().AppendASCII("appcache.db");
-
-  // First create a valid db file.
-  AppCacheDatabase db(kDbFile);
-  EXPECT_TRUE(db.LazyOpen(true));
-  EXPECT_TRUE(base::PathExists(kDbFile));
-  EXPECT_FALSE(db.was_corruption_detected());
-
-  // Break it.
-  ASSERT_TRUE(sql::test::CorruptSizeInHeader(kDbFile));
-
-  // See the the corruption is detected and reported.
-  {
-    sql::test::ScopedErrorExpecter expecter;
-    expecter.ExpectError(SQLITE_CORRUPT);
-    std::map<url::Origin, int64_t> usage_map;
-    EXPECT_FALSE(db.GetAllOriginUsage(&usage_map));
-    EXPECT_TRUE(db.was_corruption_detected());
-    EXPECT_TRUE(base::PathExists(kDbFile));
-    EXPECT_TRUE(expecter.SawExpectedErrors());
-  }
-}
-
-TEST_F(AppCacheDatabaseTest, ExperimentalFlags) {
-  const char kExperimentFlagsKey[] = "ExperimentFlags";
-  std::string kInjectedFlags("exp1,exp2");
-
-  // Real files on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile = temp_dir.GetPath().AppendASCII("appcache.db");
-  const base::FilePath kOtherFile =
-      temp_dir.GetPath().AppendASCII("other_file");
-  EXPECT_TRUE(base::WriteFile(kOtherFile, "foo"));
-  EXPECT_TRUE(base::PathExists(kOtherFile));
-
-  // Inject a non empty flags value, and verify it got there.
-  {
-    AppCacheDatabase db(kDbFile);
-    EXPECT_TRUE(db.LazyOpen(true));
-    EXPECT_TRUE(db.meta_table_->SetValue(kExperimentFlagsKey, kInjectedFlags));
-    std::string flags;
-    EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
-    EXPECT_EQ(kInjectedFlags, flags);
-  }
-
-  // If flags don't match the expected value, empty string by default,
-  // the database should be recreated and other files should be cleared out.
-  {
-    AppCacheDatabase db(kDbFile);
-    EXPECT_TRUE(db.LazyOpen(false));
-    std::string flags;
-    EXPECT_TRUE(db.meta_table_->GetValue(kExperimentFlagsKey, &flags));
-    EXPECT_TRUE(flags.empty());
-    EXPECT_FALSE(base::PathExists(kOtherFile));
-  }
-}
-
-TEST_F(AppCacheDatabaseTest, EntryRecords) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  sql::test::ScopedErrorExpecter expecter;
-  // TODO(shess): Suppressing SQLITE_CONSTRAINT because the code
-  // expects that and handles the resulting error.  Consider revising
-  // the code to use INSERT OR IGNORE (which would not throw
-  // SQLITE_CONSTRAINT) and then check ChangeCount() to see if any
-  // changes were made.
-  expecter.ExpectError(SQLITE_CONSTRAINT);
-
-  AppCacheDatabase::EntryRecord entry;
-
-  entry.cache_id = 1;
-  entry.url = GURL("http://blah/1");
-  entry.flags = AppCacheEntry::MASTER;
-  entry.response_id = 1;
-  entry.response_size = 100;
-  entry.padding_size = 10;
-  EXPECT_TRUE(db.InsertEntry(&entry));
-  EXPECT_FALSE(db.InsertEntry(&entry));
-
-  entry.cache_id = 2;
-  entry.url = GURL("http://blah/2");
-  entry.flags = AppCacheEntry::EXPLICIT;
-  entry.response_id = 2;
-  entry.response_size = 200;
-  entry.padding_size = 20;
-  EXPECT_TRUE(db.InsertEntry(&entry));
-
-  entry.cache_id = 2;
-  entry.url = GURL("http://blah/3");
-  entry.flags = AppCacheEntry::MANIFEST;
-  entry.response_id = 3;
-  entry.response_size = 300;
-  entry.padding_size = 30;
-  EXPECT_TRUE(db.InsertEntry(&entry));
-
-  std::vector<AppCacheDatabase::EntryRecord> found;
-
-  EXPECT_TRUE(db.FindEntriesForCache(1, &found));
-  EXPECT_EQ(1U, found.size());
-  EXPECT_EQ(1, found[0].cache_id);
-  EXPECT_EQ(GURL("http://blah/1"), found[0].url);
-  EXPECT_EQ(AppCacheEntry::MASTER, found[0].flags);
-  EXPECT_EQ(1, found[0].response_id);
-  EXPECT_EQ(100, found[0].response_size);
-  EXPECT_EQ(10, found[0].padding_size);
-  found.clear();
-
-  EXPECT_TRUE(db.AddEntryFlags(GURL("http://blah/1"), 1,
-                               AppCacheEntry::FOREIGN));
-  EXPECT_TRUE(db.FindEntriesForCache(1, &found));
-  EXPECT_EQ(1U, found.size());
-  EXPECT_EQ(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, found[0].flags);
-  found.clear();
-
-  EXPECT_TRUE(db.FindEntriesForCache(2, &found));
-  EXPECT_EQ(2U, found.size());
-  EXPECT_EQ(2, found[0].cache_id);
-  EXPECT_EQ(GURL("http://blah/2"), found[0].url);
-  EXPECT_EQ(AppCacheEntry::EXPLICIT, found[0].flags);
-  EXPECT_EQ(2, found[0].response_id);
-  EXPECT_EQ(200, found[0].response_size);
-  EXPECT_EQ(20, found[0].padding_size);
-  EXPECT_EQ(2, found[1].cache_id);
-  EXPECT_EQ(GURL("http://blah/3"), found[1].url);
-  EXPECT_EQ(AppCacheEntry::MANIFEST, found[1].flags);
-  EXPECT_EQ(3, found[1].response_id);
-  EXPECT_EQ(300, found[1].response_size);
-  EXPECT_EQ(30, found[1].padding_size);
-  found.clear();
-
-  EXPECT_TRUE(db.DeleteEntriesForCache(2));
-  EXPECT_TRUE(db.FindEntriesForCache(2, &found));
-  EXPECT_TRUE(found.empty());
-  found.clear();
-
-  EXPECT_TRUE(db.DeleteEntriesForCache(1));
-  EXPECT_FALSE(db.AddEntryFlags(GURL("http://blah/1"), 1,
-                                AppCacheEntry::FOREIGN));
-
-  ASSERT_TRUE(expecter.SawExpectedErrors());
-}
-
-TEST_F(AppCacheDatabaseTest, CacheRecords) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  sql::test::ScopedErrorExpecter expecter;
-  // TODO(shess): See EntryRecords test.
-  expecter.ExpectError(SQLITE_CONSTRAINT);
-
-  const AppCacheDatabase::CacheRecord kZeroRecord;
-  AppCacheDatabase::CacheRecord record;
-  EXPECT_FALSE(db.FindCache(1, &record));
-
-  record.cache_id = 1;
-  record.group_id = 1;
-  record.online_wildcard = true;
-  record.update_time = kZeroTime;
-  record.cache_size = 100;
-  record.padding_size = 10;
-  record.manifest_parser_version = 20;
-  record.manifest_scope = std::string("/foo/");
-  EXPECT_TRUE(db.InsertCache(&record));
-  EXPECT_FALSE(db.InsertCache(&record));
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindCache(1, &record));
-  EXPECT_EQ(1, record.cache_id);
-  EXPECT_EQ(1, record.group_id);
-  EXPECT_TRUE(record.online_wildcard);
-  EXPECT_TRUE(kZeroTime == record.update_time);
-  EXPECT_EQ(100, record.cache_size);
-  EXPECT_EQ(10, record.padding_size);
-  EXPECT_EQ(20, record.manifest_parser_version);
-  EXPECT_EQ("/foo/", record.manifest_scope);
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindCacheForGroup(1, &record));
-  EXPECT_EQ(1, record.cache_id);
-  EXPECT_EQ(1, record.group_id);
-  EXPECT_TRUE(record.online_wildcard);
-  EXPECT_TRUE(kZeroTime == record.update_time);
-  EXPECT_EQ(100, record.cache_size);
-  EXPECT_EQ(10, record.padding_size);
-  EXPECT_EQ(20, record.manifest_parser_version);
-  EXPECT_EQ("/foo/", record.manifest_scope);
-
-  EXPECT_TRUE(db.DeleteCache(1));
-  EXPECT_FALSE(db.FindCache(1, &record));
-  EXPECT_FALSE(db.FindCacheForGroup(1, &record));
-
-  EXPECT_TRUE(db.DeleteCache(1));
-
-  ASSERT_TRUE(expecter.SawExpectedErrors());
-}
-
-TEST_F(AppCacheDatabaseTest, GroupRecords) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  sql::test::ScopedErrorExpecter expecter;
-  // TODO(shess): See EntryRecords test.
-  expecter.ExpectError(SQLITE_CONSTRAINT);
-
-  const GURL kManifestUrl("http://blah/manifest");
-  const url::Origin kOrigin(url::Origin::Create(kManifestUrl));
-  const base::Time kLastAccessTime = base::Time::Now();
-  const base::Time kCreationTime =
-      kLastAccessTime - base::TimeDelta::FromDays(7);
-
-  const AppCacheDatabase::GroupRecord kZeroRecord;
-  AppCacheDatabase::GroupRecord record;
-  std::vector<AppCacheDatabase::GroupRecord> records;
-
-  // Behavior with an empty table
-  EXPECT_FALSE(db.FindGroup(1, &record));
-  EXPECT_FALSE(db.FindGroupForManifestUrl(kManifestUrl, &record));
-  EXPECT_TRUE(db.DeleteGroup(1));
-  EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
-  EXPECT_TRUE(records.empty());
-  EXPECT_FALSE(db.FindGroupForCache(1, &record));
-
-  record.group_id = 1;
-  record.manifest_url = kManifestUrl;
-  record.origin = kOrigin;
-  record.last_access_time = kLastAccessTime;
-  record.creation_time = kCreationTime;
-  EXPECT_TRUE(db.InsertGroup(&record));
-  EXPECT_FALSE(db.InsertGroup(&record));
-
-  record.group_id = 2;
-  EXPECT_FALSE(db.InsertGroup(&record));
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(1, record.group_id);
-  EXPECT_EQ(kManifestUrl, record.manifest_url);
-  EXPECT_EQ(kOrigin, record.origin);
-  EXPECT_EQ(kCreationTime.ToInternalValue(),
-            record.creation_time.ToInternalValue());
-  EXPECT_EQ(kLastAccessTime.ToInternalValue(),
-            record.last_access_time.ToInternalValue());
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindGroupForManifestUrl(kManifestUrl, &record));
-  EXPECT_EQ(1, record.group_id);
-  EXPECT_EQ(kManifestUrl, record.manifest_url);
-  EXPECT_EQ(kOrigin, record.origin);
-  EXPECT_EQ(kCreationTime.ToInternalValue(),
-            record.creation_time.ToInternalValue());
-  EXPECT_EQ(kLastAccessTime.ToInternalValue(),
-            record.last_access_time.ToInternalValue());
-
-  record.group_id = 2;
-  record.manifest_url = kOrigin.GetURL();
-  record.origin = kOrigin;
-  record.last_access_time = kLastAccessTime;
-  record.creation_time = kCreationTime;
-  EXPECT_TRUE(db.InsertGroup(&record));
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindGroupForManifestUrl(kOrigin.GetURL(), &record));
-  EXPECT_EQ(2, record.group_id);
-  EXPECT_EQ(kOrigin.GetURL(), record.manifest_url);
-  EXPECT_EQ(kOrigin, record.origin);
-  EXPECT_EQ(kCreationTime.ToInternalValue(),
-            record.creation_time.ToInternalValue());
-  EXPECT_EQ(kLastAccessTime.ToInternalValue(),
-            record.last_access_time.ToInternalValue());
-
-  EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
-  EXPECT_EQ(2U, records.size());
-  EXPECT_EQ(1, records[0].group_id);
-  EXPECT_EQ(kManifestUrl, records[0].manifest_url);
-  EXPECT_EQ(kOrigin, records[0].origin);
-  EXPECT_EQ(2, records[1].group_id);
-  EXPECT_EQ(kOrigin.GetURL(), records[1].manifest_url);
-  EXPECT_EQ(kOrigin, records[1].origin);
-
-  EXPECT_TRUE(db.DeleteGroup(1));
-
-  records.clear();
-  EXPECT_TRUE(db.FindGroupsForOrigin(kOrigin, &records));
-  EXPECT_EQ(1U, records.size());
-  EXPECT_EQ(2, records[0].group_id);
-  EXPECT_EQ(kOrigin.GetURL(), records[0].manifest_url);
-  EXPECT_EQ(kOrigin, records[0].origin);
-  EXPECT_EQ(kCreationTime.ToInternalValue(),
-            record.creation_time.ToInternalValue());
-  EXPECT_EQ(kLastAccessTime.ToInternalValue(),
-            record.last_access_time.ToInternalValue());
-
-  std::set<url::Origin> origins;
-  EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
-  EXPECT_EQ(1U, origins.size());
-  EXPECT_EQ(kOrigin, *(origins.begin()));
-
-  const GURL kManifest2("http://blah2/manifest");
-  const url::Origin kOrigin2(url::Origin::Create(kManifest2));
-  record.group_id = 1;
-  record.manifest_url = kManifest2;
-  record.origin = kOrigin2;
-  EXPECT_TRUE(db.InsertGroup(&record));
-
-  origins.clear();
-  EXPECT_TRUE(db.FindOriginsWithGroups(&origins));
-  EXPECT_EQ(2U, origins.size());
-  EXPECT_TRUE(origins.end() != origins.find(kOrigin));
-  EXPECT_TRUE(origins.end() != origins.find(kOrigin2));
-
-  AppCacheDatabase::CacheRecord cache_record;
-  cache_record.cache_id = 1;
-  cache_record.group_id = 1;
-  cache_record.online_wildcard = true;
-  cache_record.update_time = kZeroTime;
-  cache_record.manifest_parser_version = 1;
-  cache_record.manifest_scope = std::string("/");
-  EXPECT_TRUE(db.InsertCache(&cache_record));
-
-  record = kZeroRecord;
-  EXPECT_TRUE(db.FindGroupForCache(1, &record));
-  EXPECT_EQ(1, record.group_id);
-  EXPECT_EQ(kManifest2, record.manifest_url);
-  EXPECT_EQ(kOrigin2, record.origin);
-
-  ASSERT_TRUE(expecter.SawExpectedErrors());
-}
-
-TEST_F(AppCacheDatabaseTest, GroupAccessAndEvictionTimes) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  const GURL kManifestUrl("http://blah/manifest");
-  const url::Origin kOrigin(url::Origin::Create(kManifestUrl));
-  const base::Time kDayOne =
-      base::Time() + base::TimeDelta::FromDays(1);
-  const base::Time kDayTwo = kDayOne + base::TimeDelta::FromDays(1);
-
-  // See that the methods behave as expected with an empty db.
-  // To accommodate lazy updating, for consistency, none of them fail
-  // given ids not found in the db.
-  EXPECT_TRUE(db.UpdateEvictionTimes(1, kDayOne, kDayTwo));
-  EXPECT_TRUE(db.UpdateLastAccessTime(1, kDayOne));
-  EXPECT_TRUE(db.CommitLazyLastAccessTimes());
-  EXPECT_TRUE(db.LazyUpdateLastAccessTime(1, kDayTwo));
-  EXPECT_TRUE(db.CommitLazyLastAccessTimes());
-
-  // Insert a group at DAY1
-  AppCacheDatabase::GroupRecord record;
-  record.group_id = 1;
-  record.manifest_url = kManifestUrl;
-  record.origin = kOrigin;
-  record.creation_time = kDayOne;
-  record.last_access_time = kDayOne;
-  record.last_full_update_check_time = kDayOne;
-  record.first_evictable_error_time = kDayOne;
-  EXPECT_TRUE(db.InsertGroup(&record));
-
-  // Verify the round trip.
-  record = AppCacheDatabase::GroupRecord();
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(kDayOne, record.last_access_time);
-  EXPECT_EQ(kDayOne, record.last_full_update_check_time);
-  EXPECT_EQ(kDayOne, record.first_evictable_error_time);
-
-  // Update the times to DAY2 and verify.
-  EXPECT_TRUE(db.UpdateEvictionTimes(1, kDayTwo, kDayTwo));
-  EXPECT_TRUE(db.UpdateLastAccessTime(1, kDayTwo));
-  record = AppCacheDatabase::GroupRecord();
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(kDayTwo, record.last_access_time);
-  EXPECT_EQ(kDayTwo, record.last_full_update_check_time);
-  EXPECT_EQ(kDayTwo, record.first_evictable_error_time);
-
-  // Lazy update back to DAY1 and verify its reflected without having committed.
-  EXPECT_TRUE(db.lazy_last_access_times_.empty());
-  EXPECT_TRUE(db.LazyUpdateLastAccessTime(1, kDayOne));
-  EXPECT_FALSE(db.lazy_last_access_times_.empty());
-  record = AppCacheDatabase::GroupRecord();
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(kDayOne, record.last_access_time);
-
-  // Commit the lazy value and verify it sticks.
-  EXPECT_TRUE(db.CommitLazyLastAccessTimes());
-  EXPECT_TRUE(db.lazy_last_access_times_.empty());
-  record = AppCacheDatabase::GroupRecord();
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(kDayOne, record.last_access_time);
-
-  // Verify a bad lazy group id doesn't fail to commit the good ones on DAY2.
-  EXPECT_TRUE(db.LazyUpdateLastAccessTime(1, kDayTwo));
-  EXPECT_TRUE(db.LazyUpdateLastAccessTime(2, kDayTwo));
-  EXPECT_EQ(2u, db.lazy_last_access_times_.size());
-  EXPECT_TRUE(db.CommitLazyLastAccessTimes());
-  EXPECT_TRUE(db.lazy_last_access_times_.empty());
-  record = AppCacheDatabase::GroupRecord();
-  EXPECT_TRUE(db.FindGroup(1, &record));
-  EXPECT_EQ(kDayTwo, record.last_access_time);
-}
-
-TEST_F(AppCacheDatabaseTest, NamespaceRecords) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  sql::test::ScopedErrorExpecter expecter;
-  // TODO(shess): See EntryRecords test.
-  expecter.ExpectError(SQLITE_CONSTRAINT);
-
-  const GURL kFooNameSpace1("http://foo/namespace1");
-  const GURL kFooNameSpace2("http://foo/namespace2");
-  const GURL kFooFallbackEntry("http://foo/entry");
-  const url::Origin kFooOrigin(url::Origin::Create(kFooNameSpace1));
-  const GURL kBarNameSpace1("http://bar/namespace1");
-  const GURL kBarNameSpace2("http://bar/namespace2");
-  const GURL kBarFallbackEntry("http://bar/entry");
-  const url::Origin kBarOrigin(url::Origin::Create(kBarNameSpace1));
-
-  const AppCacheDatabase::NamespaceRecord kZeroRecord;
-  AppCacheDatabase::NamespaceRecord record;
-  std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
-  std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
-
-  // Behavior with an empty table
-  EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
-  EXPECT_TRUE(fallbacks.empty());
-  EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
-  EXPECT_TRUE(fallbacks.empty());
-  EXPECT_TRUE(db.DeleteNamespacesForCache(1));
-
-  // Two records for two differenent caches in the Foo origin.
-  record.cache_id = 1;
-  record.origin = kFooOrigin;
-  record.namespace_.namespace_url = kFooNameSpace1;
-  record.namespace_.target_url = kFooFallbackEntry;
-  EXPECT_TRUE(db.InsertNamespace(&record));
-  EXPECT_FALSE(db.InsertNamespace(&record));
-
-  record.cache_id = 2;
-  record.origin = kFooOrigin;
-  record.namespace_.namespace_url = kFooNameSpace2;
-  record.namespace_.target_url = kFooFallbackEntry;
-  EXPECT_TRUE(db.InsertNamespace(&record));
-
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForCache(1, &intercepts, &fallbacks));
-  EXPECT_EQ(1U, fallbacks.size());
-  EXPECT_EQ(1, fallbacks[0].cache_id);
-  EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
-  EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
-  EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
-
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForCache(2, &intercepts, &fallbacks));
-  EXPECT_EQ(1U, fallbacks.size());
-  EXPECT_EQ(2, fallbacks[0].cache_id);
-  EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
-  EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
-  EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
-
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
-  EXPECT_EQ(2U, fallbacks.size());
-  EXPECT_EQ(1, fallbacks[0].cache_id);
-  EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
-  EXPECT_EQ(kFooNameSpace1, fallbacks[0].namespace_.namespace_url);
-  EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
-  EXPECT_EQ(2, fallbacks[1].cache_id);
-  EXPECT_EQ(kFooOrigin, fallbacks[1].origin);
-  EXPECT_EQ(kFooNameSpace2, fallbacks[1].namespace_.namespace_url);
-  EXPECT_EQ(kFooFallbackEntry, fallbacks[1].namespace_.target_url);
-
-  EXPECT_TRUE(db.DeleteNamespacesForCache(1));
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForOrigin(kFooOrigin, &intercepts, &fallbacks));
-  EXPECT_EQ(1U, fallbacks.size());
-  EXPECT_EQ(2, fallbacks[0].cache_id);
-  EXPECT_EQ(kFooOrigin, fallbacks[0].origin);
-  EXPECT_EQ(kFooNameSpace2, fallbacks[0].namespace_.namespace_url);
-  EXPECT_EQ(kFooFallbackEntry, fallbacks[0].namespace_.target_url);
-
-  // Two more records for the same cache in the Bar origin.
-  record.cache_id = 3;
-  record.origin = kBarOrigin;
-  record.namespace_.namespace_url = kBarNameSpace1;
-  record.namespace_.target_url = kBarFallbackEntry;
-  EXPECT_TRUE(db.InsertNamespace(&record));
-
-  record.cache_id = 3;
-  record.origin = kBarOrigin;
-  record.namespace_.namespace_url = kBarNameSpace2;
-  record.namespace_.target_url = kBarFallbackEntry;
-  EXPECT_TRUE(db.InsertNamespace(&record));
-
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForCache(3, &intercepts, &fallbacks));
-  EXPECT_EQ(2U, fallbacks.size());
-
-  fallbacks.clear();
-  EXPECT_TRUE(db.FindNamespacesForOrigin(kBarOrigin, &intercepts, &fallbacks));
-  EXPECT_EQ(2U, fallbacks.size());
-
-  ASSERT_TRUE(expecter.SawExpectedErrors());
-}
-
-TEST_F(AppCacheDatabaseTest, OnlineSafeListRecords) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  const GURL kFooNameSpace1("http://foo/namespace1");
-  const GURL kFooNameSpace2("http://foo/namespace2");
-  const GURL kBarNameSpace1("http://bar/namespace1");
-
-  const AppCacheDatabase::OnlineSafeListRecord kZeroRecord;
-  AppCacheDatabase::OnlineSafeListRecord record;
-  std::vector<AppCacheDatabase::OnlineSafeListRecord> records;
-
-  // Behavior with an empty table
-  EXPECT_TRUE(db.FindOnlineSafeListForCache(1, &records));
-  EXPECT_TRUE(records.empty());
-  EXPECT_TRUE(db.DeleteOnlineSafeListForCache(1));
-
-  record.cache_id = 1;
-  record.namespace_url = kFooNameSpace1;
-  EXPECT_TRUE(db.InsertOnlineSafeList(&record));
-  record.namespace_url = kFooNameSpace2;
-  EXPECT_TRUE(db.InsertOnlineSafeList(&record));
-  records.clear();
-  EXPECT_TRUE(db.FindOnlineSafeListForCache(1, &records));
-  EXPECT_EQ(2U, records.size());
-  EXPECT_EQ(1, records[0].cache_id);
-  EXPECT_EQ(kFooNameSpace1, records[0].namespace_url);
-  EXPECT_EQ(1, records[1].cache_id);
-  EXPECT_EQ(kFooNameSpace2, records[1].namespace_url);
-
-  record.cache_id = 2;
-  record.namespace_url = kBarNameSpace1;
-  EXPECT_TRUE(db.InsertOnlineSafeList(&record));
-  records.clear();
-  EXPECT_TRUE(db.FindOnlineSafeListForCache(2, &records));
-  EXPECT_EQ(1U, records.size());
-
-  EXPECT_TRUE(db.DeleteOnlineSafeListForCache(1));
-  records.clear();
-  EXPECT_TRUE(db.FindOnlineSafeListForCache(1, &records));
-  EXPECT_TRUE(records.empty());
-}
-
-TEST_F(AppCacheDatabaseTest, DeletableResponseIds) {
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  sql::test::ScopedErrorExpecter expecter;
-  // TODO(shess): See EntryRecords test.
-  expecter.ExpectError(SQLITE_CONSTRAINT);
-
-  std::vector<int64_t> ids;
-
-  EXPECT_TRUE(db.GetDeletableResponseIds(
-      &ids, std::numeric_limits<int64_t>::max(), 100));
-  EXPECT_TRUE(ids.empty());
-  ids.push_back(0);
-  EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
-  EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
-
-  ids.clear();
-  EXPECT_TRUE(db.GetDeletableResponseIds(
-      &ids, std::numeric_limits<int64_t>::max(), 100));
-  EXPECT_EQ(1U, ids.size());
-  EXPECT_EQ(0, ids[0]);
-
-  int64_t unused, deleteable_response_rowid;
-  unused = deleteable_response_rowid = 0;
-  EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
-                                    &deleteable_response_rowid));
-  EXPECT_EQ(1, deleteable_response_rowid);
-
-
-  // Expected to fail due to the duplicate id, 0 is already in the table.
-  ids.clear();
-  ids.push_back(0);
-  ids.push_back(1);
-  EXPECT_FALSE(db.InsertDeletableResponseIds(ids));
-
-  ids.clear();
-  for (int i = 1; i < 10; ++i)
-    ids.push_back(i);
-  EXPECT_TRUE(db.InsertDeletableResponseIds(ids));
-  EXPECT_TRUE(db.FindLastStorageIds(&unused, &unused, &unused,
-                                    &deleteable_response_rowid));
-  EXPECT_EQ(10, deleteable_response_rowid);
-
-  ids.clear();
-  EXPECT_TRUE(db.GetDeletableResponseIds(
-      &ids, std::numeric_limits<int64_t>::max(), 100));
-  EXPECT_EQ(10U, ids.size());
-  for (int i = 0; i < 10; ++i)
-    EXPECT_EQ(i, ids[i]);
-
-  // Ensure the limit is respected.
-  ids.clear();
-  EXPECT_TRUE(
-      db.GetDeletableResponseIds(&ids, std::numeric_limits<int64_t>::max(), 5));
-  EXPECT_EQ(5U, ids.size());
-  for (int i = 0; i < static_cast<int>(ids.size()); ++i)
-    EXPECT_EQ(i, ids[i]);
-
-  // Ensure the max_rowid is respected (the first rowid is 1).
-  ids.clear();
-  EXPECT_TRUE(db.GetDeletableResponseIds(&ids, 5, 100));
-  EXPECT_EQ(5U, ids.size());
-  for (int i = 0; i < static_cast<int>(ids.size()); ++i)
-    EXPECT_EQ(i, ids[i]);
-
-  // Ensure that we can delete from the table.
-  EXPECT_TRUE(db.DeleteDeletableResponseIds(ids));
-  ids.clear();
-  EXPECT_TRUE(db.GetDeletableResponseIds(
-      &ids, std::numeric_limits<int64_t>::max(), 100));
-  EXPECT_EQ(5U, ids.size());
-  for (int i = 0; i < static_cast<int>(ids.size()); ++i)
-    EXPECT_EQ(i + 5, ids[i]);
-
-  ASSERT_TRUE(expecter.SawExpectedErrors());
-}
-
-TEST_F(AppCacheDatabaseTest, OriginUsage) {
-  const GURL kManifestUrl("http://blah/manifest");
-  const GURL kManifestUrl2("http://blah/manifest2");
-  const url::Origin kOrigin = url::Origin::Create(kManifestUrl);
-  const GURL kOtherOriginManifestUrl("http://other/manifest");
-  const url::Origin kOtherOrigin = url::Origin::Create(kOtherOriginManifestUrl);
-
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  std::vector<AppCacheDatabase::CacheRecord> cache_records;
-  EXPECT_EQ(0, db.GetOriginUsage(kOrigin));
-
-  AppCacheDatabase::GroupRecord group_record;
-  group_record.group_id = 1;
-  group_record.manifest_url = kManifestUrl;
-  group_record.origin = kOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-  AppCacheDatabase::CacheRecord cache_record;
-  cache_record.cache_id = 1;
-  cache_record.group_id = 1;
-  cache_record.online_wildcard = true;
-  cache_record.update_time = kZeroTime;
-  cache_record.cache_size = 100;
-  cache_record.padding_size = 1;
-  cache_record.manifest_parser_version = 1;
-  cache_record.manifest_scope = std::string("/");
-  EXPECT_TRUE(db.InsertCache(&cache_record));
-
-  EXPECT_EQ(101, db.GetOriginUsage(kOrigin));
-
-  group_record.group_id = 2;
-  group_record.manifest_url = kManifestUrl2;
-  group_record.origin = kOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-  cache_record.cache_id = 2;
-  cache_record.group_id = 2;
-  cache_record.online_wildcard = true;
-  cache_record.update_time = kZeroTime;
-  cache_record.cache_size = 1000;
-  cache_record.padding_size = 1;
-  EXPECT_TRUE(db.InsertCache(&cache_record));
-
-  EXPECT_EQ(1102, db.GetOriginUsage(kOrigin));
-
-  group_record.group_id = 3;
-  group_record.manifest_url = kOtherOriginManifestUrl;
-  group_record.origin = kOtherOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-  cache_record.cache_id = 3;
-  cache_record.group_id = 3;
-  cache_record.online_wildcard = true;
-  cache_record.update_time = kZeroTime;
-  cache_record.cache_size = 5000;
-  cache_record.padding_size = 1;
-  EXPECT_TRUE(db.InsertCache(&cache_record));
-
-  EXPECT_EQ(5001, db.GetOriginUsage(kOtherOrigin));
-
-  std::map<url::Origin, int64_t> usage_map;
-  EXPECT_TRUE(db.GetAllOriginUsage(&usage_map));
-  EXPECT_EQ(2U, usage_map.size());
-  EXPECT_EQ(1102, usage_map[kOrigin]);
-  EXPECT_EQ(5001, usage_map[kOtherOrigin]);
-}
-
-TEST_F(AppCacheDatabaseTest, FindCachesForOrigin) {
-  const GURL kManifestUrl("http://blah/manifest");
-  const GURL kManifestUrl2("http://blah/manifest2");
-  const url::Origin kOrigin = url::Origin::Create(kManifestUrl);
-  const GURL kOtherOriginManifestUrl("http://other/manifest");
-  const url::Origin kOtherOrigin = url::Origin::Create(kOtherOriginManifestUrl);
-
-  const base::FilePath kEmptyPath;
-  AppCacheDatabase db(kEmptyPath);
-  EXPECT_TRUE(db.LazyOpen(true));
-
-  std::vector<AppCacheDatabase::CacheRecord> cache_records;
-  EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
-  EXPECT_TRUE(cache_records.empty());
-
-  // Create 2 Groups with the same origin, and 1 Group with a different origin.
-  AppCacheDatabase::GroupRecord group_record;
-  group_record.group_id = 1;
-  group_record.manifest_url = kManifestUrl;
-  group_record.origin = kOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-  group_record.group_id = 2;
-  group_record.manifest_url = kManifestUrl2;
-  group_record.origin = kOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-  group_record.group_id = 3;
-  group_record.manifest_url = kOtherOriginManifestUrl;
-  group_record.origin = kOtherOrigin;
-  EXPECT_TRUE(db.InsertGroup(&group_record));
-
-  // Add a Cache to each of the 3 Groups.
-  AppCacheDatabase::CacheRecord cache_record;
-  for (int i = 1; i < 4; ++i) {
-    cache_record.cache_id = i;
-    cache_record.group_id = i;
-    cache_record.online_wildcard = true;
-    cache_record.update_time = kZeroTime;
-    cache_record.cache_size = 100;
-    cache_record.padding_size = 1000;
-    cache_record.manifest_parser_version = 1;
-    cache_record.manifest_scope = std::string("/");
-    EXPECT_TRUE(db.InsertCache(&cache_record));
-  }
-
-  EXPECT_TRUE(db.FindCachesForOrigin(kOrigin, &cache_records));
-  EXPECT_EQ(2U, cache_records.size());
-  cache_records.clear();
-  EXPECT_TRUE(db.FindCachesForOrigin(kOtherOrigin, &cache_records));
-  EXPECT_EQ(1U, cache_records.size());
-}
-
-TEST_F(AppCacheDatabaseTest,
-       UpgradeSchemaForVersionsWithoutSupportedMigrations) {
-  // Real file on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile =
-      temp_dir.GetPath().AppendASCII("deprecated.db");
-
-  // Create a database with a table name that does not show up in the AppCache
-  // schema. This table would not be touched by any migration, so its existence
-  // indicates that the database was not nuked.
-  {
-    sql::Database db;
-    EXPECT_TRUE(db.Open(kDbFile));
-
-    sql::MetaTable meta_table;
-    EXPECT_TRUE(meta_table.Init(&db, 6, 6));
-
-    static const char kSchemaSql[] =
-        "CREATE TABLE Unused(id INTEGER PRIMARY KEY)";
-    EXPECT_TRUE(db.Execute(kSchemaSql));
-
-    EXPECT_TRUE(db.DoesColumnExist("Unused", "id"));
-  }
-
-  // Open that database and verify that it got nuked.
-  AppCacheDatabase db(kDbFile);
-  EXPECT_TRUE(db.LazyOpen(/*create_if_needed=*/false));
-  EXPECT_FALSE(db.db_->DoesColumnExist("Unused", "id"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "padding_size"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Entries", "padding_size"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_parser_version"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_scope"));
-  EXPECT_EQ(10, db.meta_table_->GetVersionNumber());
-  EXPECT_EQ(10, db.meta_table_->GetCompatibleVersionNumber());
-}
-
-TEST_F(AppCacheDatabaseTest, UpgradeSchemaFrom7) {
-  // Real file on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile =
-      temp_dir.GetPath().AppendASCII("upgrade7to8.db");
-
-  {
-    sql::Database db;
-    EXPECT_TRUE(db.Open(kDbFile));
-
-    sql::MetaTable meta_table;
-    EXPECT_TRUE(meta_table.Init(&db, 7, 7));
-
-    // Create a database with a table name that does not show up in the AppCache
-    // schema. Its persistence across the migration indicates that the migration
-    // did not nuke the database.
-    static const char kCreateUnusedTableSql[] =
-        "CREATE TABLE Unused(id INTEGER PRIMARY KEY)";
-    EXPECT_TRUE(db.Execute(kCreateUnusedTableSql));
-
-    // Include tables/columns that are needed to run the 7-to-9 backfill.
-    static const char kCreateGroupsSql[] =
-        "CREATE TABLE Groups(group_id INTEGER PRIMARY KEY, manifest_url TEXT)";
-    static const char kCreateCachesSql[] =
-        "CREATE TABLE Caches(cache_id INTEGER PRIMARY KEY, group_id INTEGER)";
-    static const char kCreateEntriesSql[] =
-        "CREATE TABLE Entries(cache_id INTEGER, url TEXT, response_id INTEGER)";
-    static const char kCreateNamespacesSql[] =
-        "CREATE TABLE Namespaces(cache_id INTEGER, origin TEXT, type INTEGER,"
-        "namespace_url TEXT, target_url TEXT, is_pattern INTEGER)";
-    EXPECT_TRUE(db.Execute(kCreateGroupsSql));
-    EXPECT_TRUE(db.Execute(kCreateCachesSql));
-    EXPECT_TRUE(db.Execute(kCreateEntriesSql));
-    EXPECT_TRUE(db.Execute(kCreateNamespacesSql));
-
-    // Insert version 7 records (with 0 padding) to test the backfill.
-    static const char kInsertGroupSql[] =
-        "INSERT INTO Groups (group_id, manifest_url) VALUES "
-        " (1, 'manifest_url'),"
-        " (2, 'https://blah/manifest_url'),"
-        " (3, 'https://blah/foo/manifest_url')";
-    static const char kInsertCacheSql[] =
-        "INSERT INTO Caches (cache_id, group_id) VALUES(1, 1), (2, 2), (3, 3)";
-    static const char kInsertEntrySql[] =
-        "INSERT INTO Entries (cache_id, url, response_id) VALUES (1, 'url', 1)";
-    EXPECT_TRUE(db.Execute(kInsertGroupSql));
-    EXPECT_TRUE(db.Execute(kInsertCacheSql));
-    EXPECT_TRUE(db.Execute(kInsertEntrySql));
-  }
-
-  AppCacheDatabase db(kDbFile);
-  EXPECT_TRUE(db.LazyOpen(/*create_if_needed=*/false));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Unused", "id"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "padding_size"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Entries", "padding_size"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_parser_version"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_scope"));
-
-  static const char kFindCacheSql[] =
-      "SELECT padding_size, cache_id FROM Caches WHERE cache_id = 1";
-  sql::Statement find_cache_statement(
-      db.db_->GetUniqueStatement(kFindCacheSql));
-  EXPECT_TRUE(find_cache_statement.Step());
-  int64_t cache_padding_size = find_cache_statement.ColumnInt64(0);
-
-  static const char kFindEntrySql[] =
-      "SELECT padding_size, response_id FROM Entries WHERE response_id = 1";
-  sql::Statement find_entry_statement(
-      db.db_->GetUniqueStatement(kFindEntrySql));
-  EXPECT_TRUE(find_entry_statement.Step());
-  int64_t entry_padding_size = find_entry_statement.ColumnInt64(0);
-
-  EXPECT_GE(cache_padding_size, 0);
-  EXPECT_EQ(cache_padding_size, entry_padding_size);
-
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 1), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 1), "/");
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 2), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 2), "/");
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 3), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 3), "/");
-}
-
-TEST_F(AppCacheDatabaseTest, UpgradeSchemaFrom8) {
-  // Real file on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile =
-      temp_dir.GetPath().AppendASCII("upgrade8to9.db");
-
-  {
-    sql::Database db;
-    EXPECT_TRUE(db.Open(kDbFile));
-
-    sql::MetaTable meta_table;
-    EXPECT_TRUE(meta_table.Init(&db, 8, 8));
-
-    // Create a database with a table name that does not show up in the AppCache
-    // schema. Its persistence across the migration indicates that the migration
-    // did not nuke the database.
-    static const char kCreateUnusedTableSql[] =
-        "CREATE TABLE Unused(id INTEGER PRIMARY KEY)";
-    EXPECT_TRUE(db.Execute(kCreateUnusedTableSql));
-
-    // Include tables/columns that are needed to run the 8-to-9 backfill.
-    static const char kCreateGroupsSql[] =
-        "CREATE TABLE Groups(group_id INTEGER PRIMARY KEY, manifest_url TEXT)";
-    static const char kCreateCachesSql[] =
-        "CREATE TABLE Caches(cache_id INTEGER PRIMARY KEY, group_id INTEGER)";
-    static const char kCreateEntriesSql[] =
-        "CREATE TABLE Entries(cache_id INTEGER, url TEXT,"
-        "flags INTEGER, response_id INTEGER, response_size INTEGER,"
-        "padding_size INTEGER)";
-    static const char kCreateNamespacesSql[] =
-        "CREATE TABLE Namespaces(cache_id INTEGER, origin TEXT, type INTEGER,"
-        "namespace_url TEXT, target_url TEXT, is_pattern INTEGER)";
-    EXPECT_TRUE(db.Execute(kCreateGroupsSql));
-    EXPECT_TRUE(db.Execute(kCreateCachesSql));
-    EXPECT_TRUE(db.Execute(kCreateEntriesSql));
-    EXPECT_TRUE(db.Execute(kCreateNamespacesSql));
-
-    // Insert a version 8 record to test the backfill.
-    static const char kInsertGroupSql[] =
-        "INSERT INTO Groups (group_id, manifest_url) VALUES "
-        " (1, 'manifest_url'),"
-        " (2, 'https://blah/manifest_url'),"
-        " (3, 'https://blah/foo/manifest_url')";
-    static const char kInsertCacheSql[] =
-        "INSERT INTO Caches (cache_id, group_id) VALUES(1, 1), (2, 2), (3, 3)";
-    EXPECT_TRUE(db.Execute(kInsertGroupSql));
-    EXPECT_TRUE(db.Execute(kInsertCacheSql));
-  }
-
-  AppCacheDatabase db(kDbFile);
-  EXPECT_TRUE(db.LazyOpen(/*create_if_needed=*/false));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Unused", "id"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_parser_version"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "manifest_scope"));
-
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 1), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 1), "/");
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 2), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 2), "/");
-  EXPECT_EQ(GetCacheManifestParserVersion(db, 3), 0);
-  EXPECT_EQ(GetCacheManifestScope(db, 3), "/");
-}
-
-TEST_F(AppCacheDatabaseTest, UpgradeSchemaFrom9) {
-  // Real file on disk for this test.
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kDbFile =
-      temp_dir.GetPath().AppendASCII("upgrade9to10.db");
-
-  {
-    sql::Database db;
-    EXPECT_TRUE(db.Open(kDbFile));
-
-    sql::MetaTable meta_table;
-    EXPECT_TRUE(meta_table.Init(&db, 9, 9));
-
-    // Create a database with a table name that does not show up in the AppCache
-    // schema. Its persistence across the migration indicates that the migration
-    // did not nuke the database.
-    static const char kCreateUnusedTableSql[] =
-        "CREATE TABLE Unused(id INTEGER PRIMARY KEY)";
-    EXPECT_TRUE(db.Execute(kCreateUnusedTableSql));
-
-    static const char kCreateGroupsSql[] =
-        "CREATE TABLE Groups(group_id INTEGER PRIMARY KEY, origin TEXT,"
-        "manifest_url TEXT, creation_time INTEGER, last_access_time INTEGER,"
-        "last_full_update_check_time INTEGER,"
-        "first_evictalbe_error_time INTEGER)";
-    static const char kCreateCachesSql[] =
-        "CREATE TABLE Caches(cache_id INTEGER PRIMARY KEY, group_id INTEGER,"
-        "online_wildcard INTEGER, update_time INTEGER, cache_size INTEGER,"
-        "padding_size INTEGER, manifest_parser_version INTEGER,"
-        "manifest_scope TEXT)";
-    static const char kCreateEntriesSql[] =
-        "CREATE TABLE Entries(cache_id INTEGER, url TEXT,"
-        "flags INTEGER, response_id INTEGER, response_size INTEGER,"
-        "padding_size INTEGER)";
-    static const char kCreateNamespacesSql[] =
-        "CREATE TABLE Namespaces(cache_id INTEGER, origin TEXT, type INTEGER,"
-        "namespace_url TEXT, target_url TEXT, is_pattern INTEGER)";
-    EXPECT_TRUE(db.Execute(kCreateGroupsSql));
-    EXPECT_TRUE(db.Execute(kCreateCachesSql));
-    EXPECT_TRUE(db.Execute(kCreateEntriesSql));
-    EXPECT_TRUE(db.Execute(kCreateNamespacesSql));
-
-    static const char kInsertCacheSql[] =
-        "INSERT INTO Caches(cache_id, group_id) VALUES (1, 1)";
-    static const char kInsertGroupSql[] =
-        "INSERT INTO Groups (group_id, manifest_url) VALUES "
-        " (1, 'manifest_url')";
-    static const char kInsertEntrySql[] =
-        "INSERT INTO Entries (cache_id, url, response_id) VALUES (1, 'url', 1)";
-    static const char kInsertNamespaceSql[] =
-        "INSERT INTO Namespaces(cache_id, origin) VALUES (1, 'origin')";
-
-    EXPECT_TRUE(db.Execute(kInsertCacheSql));
-    EXPECT_TRUE(db.Execute(kInsertGroupSql));
-    EXPECT_TRUE(db.Execute(kInsertEntrySql));
-    EXPECT_TRUE(db.Execute(kInsertNamespaceSql));
-  }
-
-  AppCacheDatabase db(kDbFile);
-  EXPECT_TRUE(db.LazyOpen(/*create_if_needed=*/false));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Unused", "id"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Caches", "token_expires"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Groups", "token_expires"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Entries", "token_expires"));
-  EXPECT_TRUE(db.db_->DoesColumnExist("Namespaces", "token_expires"));
-
-  static const char kFindCacheSql[] =
-      "SELECT token_expires FROM Entries WHERE cache_id = 1";
-  sql::Statement find_cache_statement(
-      db.db_->GetUniqueStatement(kFindCacheSql));
-  EXPECT_TRUE(find_cache_statement.Step());
-  EXPECT_EQ(0, find_cache_statement.ColumnInt64(0));
-
-  static const char kFindGroupSql[] =
-      "SELECT token_expires FROM Entries WHERE cache_id = 1";
-  sql::Statement find_group_statement(
-      db.db_->GetUniqueStatement(kFindGroupSql));
-  EXPECT_TRUE(find_group_statement.Step());
-  EXPECT_EQ(0, find_group_statement.ColumnInt64(0));
-
-  static const char kFindEntrySql[] =
-      "SELECT token_expires FROM Entries WHERE cache_id = 1";
-  sql::Statement find_entry_statement(
-      db.db_->GetUniqueStatement(kFindEntrySql));
-  EXPECT_TRUE(find_entry_statement.Step());
-  EXPECT_EQ(0, find_entry_statement.ColumnInt64(0));
-
-  static const char kFindNamespaceSql[] =
-      "SELECT token_expires FROM Namespaces WHERE cache_id = 1";
-  sql::Statement find_namespace_statement(
-      db.db_->GetUniqueStatement(kFindNamespaceSql));
-  EXPECT_TRUE(find_namespace_statement.Step());
-  EXPECT_EQ(0, find_namespace_statement.ColumnInt64(0));
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_disk_cache_unittest.cc b/content/browser/appcache/appcache_disk_cache_unittest.cc
deleted file mode 100644
index e797fbb4..0000000
--- a/content/browser/appcache/appcache_disk_cache_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_disk_cache.h"
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "net/base/completion_repeating_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/base/test_completion_callback.h"
-#include "net/disk_cache/disk_cache.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class AppCacheDiskCacheTest : public testing::Test {
- public:
-  AppCacheDiskCacheTest() = default;
-
-  void SetUp() override {
-    ASSERT_TRUE(directory_.CreateUniqueTempDir());
-    completion_callback_ = base::BindRepeating(
-        &AppCacheDiskCacheTest::OnComplete, base::Unretained(this));
-  }
-
-  void TearDown() override { task_environment_.RunUntilIdle(); }
-
-  void FlushCacheTasks() {
-    disk_cache::FlushCacheThreadForTesting();
-    task_environment_.RunUntilIdle();
-  }
-
-  void OnComplete(int err) {
-    completion_results_.push_back(err);
-  }
-
-  base::test::TaskEnvironment task_environment_;
-  base::ScopedTempDir directory_;
-  net::CompletionRepeatingCallback completion_callback_;
-  std::vector<int> completion_results_;
-
-  static const int k10MBytes = 10 * 1024 * 1024;
-};
-
-TEST_F(AppCacheDiskCacheTest, DisablePriorToInitCompletion) {
-  AppCacheDiskCacheEntry* entry = nullptr;
-
-  // Create an instance and start it initializing, queue up
-  // one of each kind of "entry" function.
-  auto disk_cache = std::make_unique<AppCacheDiskCache>();
-  EXPECT_FALSE(disk_cache->is_disabled());
-  disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
-                                  base::OnceClosure(), completion_callback_);
-  disk_cache->CreateEntry(1, &entry, completion_callback_);
-  disk_cache->OpenEntry(2, &entry, completion_callback_);
-  disk_cache->DoomEntry(3, completion_callback_);
-
-  // Pull the plug on all that.
-  EXPECT_FALSE(disk_cache->is_disabled());
-  disk_cache->Disable();
-  EXPECT_TRUE(disk_cache->is_disabled());
-
-  FlushCacheTasks();
-
-  EXPECT_EQ(nullptr, entry);
-  EXPECT_EQ(4u, completion_results_.size());
-  for (const auto& result : completion_results_) {
-    EXPECT_EQ(net::ERR_ABORTED, result);
-  }
-
-  // Ensure the directory can be deleted at this point.
-  EXPECT_TRUE(base::DirectoryExists(directory_.GetPath()));
-  EXPECT_FALSE(base::IsDirectoryEmpty(directory_.GetPath()));
-  EXPECT_TRUE(base::DeletePathRecursively(directory_.GetPath()));
-  EXPECT_FALSE(base::DirectoryExists(directory_.GetPath()));
-}
-
-TEST_F(AppCacheDiskCacheTest, DisableAfterInitted) {
-  // Create an instance and let it fully init.
-  auto disk_cache = std::make_unique<AppCacheDiskCache>();
-  EXPECT_FALSE(disk_cache->is_disabled());
-  disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
-                                  base::OnceClosure(), completion_callback_);
-  FlushCacheTasks();
-  EXPECT_EQ(1u, completion_results_.size());
-  EXPECT_EQ(net::OK, completion_results_[0]);
-
-  // Pull the plug
-  disk_cache->Disable();
-  FlushCacheTasks();
-
-  // Ensure the directory can be deleted at this point.
-  EXPECT_TRUE(base::DirectoryExists(directory_.GetPath()));
-  EXPECT_FALSE(base::IsDirectoryEmpty(directory_.GetPath()));
-  EXPECT_TRUE(base::DeletePathRecursively(directory_.GetPath()));
-  EXPECT_FALSE(base::DirectoryExists(directory_.GetPath()));
-
-  // Methods should return immediately when disabled and not invoke
-  // the callback at all.
-  AppCacheDiskCacheEntry* entry = nullptr;
-  completion_results_.clear();
-  EXPECT_EQ(net::ERR_ABORTED,
-            disk_cache->CreateEntry(1, &entry, completion_callback_));
-  EXPECT_EQ(net::ERR_ABORTED,
-            disk_cache->OpenEntry(2, &entry, completion_callback_));
-  EXPECT_EQ(net::ERR_ABORTED,
-            disk_cache->DoomEntry(3, completion_callback_));
-  FlushCacheTasks();
-  EXPECT_TRUE(completion_results_.empty());
-}
-
-// Flaky on Android: http://crbug.com/339534
-TEST_F(AppCacheDiskCacheTest, DISABLED_DisableWithEntriesOpen) {
-  // Create an instance and let it fully init.
-  auto disk_cache = std::make_unique<AppCacheDiskCache>();
-  EXPECT_FALSE(disk_cache->is_disabled());
-  disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
-                                  base::OnceClosure(), completion_callback_);
-  FlushCacheTasks();
-  EXPECT_EQ(1u, completion_results_.size());
-  EXPECT_EQ(net::OK, completion_results_[0]);
-
-  // Note: We don't have detailed expectations of the DiskCache
-  // operations because on android it's really SimpleCache which
-  // does behave differently.
-  //
-  // What matters for the corruption handling and service reinitiazation
-  // is that the directory can be deleted after the calling Disable() method,
-  // and we do have expectations about that.
-
-  // Create/open some entries.
-  AppCacheDiskCacheEntry* entry1 = nullptr;
-  AppCacheDiskCacheEntry* entry2 = nullptr;
-  disk_cache->CreateEntry(1, &entry1, completion_callback_);
-  disk_cache->CreateEntry(2, &entry2, completion_callback_);
-  FlushCacheTasks();
-  EXPECT_TRUE(entry1);
-  EXPECT_TRUE(entry2);
-
-  // Write something to one of the entries and flush it.
-  const char* kData = "Hello";
-  const int kDataLen = strlen(kData) + 1;
-  scoped_refptr<net::IOBuffer> write_buf =
-      base::MakeRefCounted<net::WrappedIOBuffer>(kData);
-  entry1->Write(0, 0, write_buf.get(), kDataLen, completion_callback_);
-  FlushCacheTasks();
-
-  // Queue up a read and a write.
-  scoped_refptr<net::IOBuffer> read_buf =
-      base::MakeRefCounted<net::IOBuffer>(kDataLen);
-  entry1->Read(0, 0, read_buf.get(), kDataLen, completion_callback_);
-  entry2->Write(0, 0, write_buf.get(), kDataLen, completion_callback_);
-
-  // Pull the plug
-  disk_cache->Disable();
-  FlushCacheTasks();
-
-  // Ensure the directory can be deleted at this point.
-  EXPECT_TRUE(base::DirectoryExists(directory_.GetPath()));
-  EXPECT_FALSE(base::IsDirectoryEmpty(directory_.GetPath()));
-  EXPECT_TRUE(base::DeletePathRecursively(directory_.GetPath()));
-  EXPECT_FALSE(base::DirectoryExists(directory_.GetPath()));
-
-  disk_cache.reset(nullptr);
-
-  // Also, new IO operations should fail immediately.
-  EXPECT_EQ(
-      net::ERR_ABORTED,
-      entry1->Read(0, 0, read_buf.get(), kDataLen, completion_callback_));
-  entry1->Close();
-  entry2->Close();
-
-  FlushCacheTasks();
-}
-
-TEST_F(AppCacheDiskCacheTest, CleanupCallback) {
-  // Test that things delete fine when we disable the cache and wait for
-  // the cleanup callback.
-
-  net::TestClosure cleanup_done;
-  net::TestCompletionCallback init_done;
-  auto disk_cache = std::make_unique<AppCacheDiskCache>();
-  EXPECT_FALSE(disk_cache->is_disabled());
-  disk_cache->InitWithDiskBackend(directory_.GetPath(), false,
-                                  cleanup_done.closure(), init_done.callback());
-  EXPECT_EQ(net::OK, init_done.WaitForResult());
-
-  disk_cache->Disable();
-  cleanup_done.WaitForResult();
-
-  // Ensure the directory can be deleted at this point.
-  EXPECT_TRUE(base::DirectoryExists(directory_.GetPath()));
-  EXPECT_FALSE(base::IsDirectoryEmpty(directory_.GetPath()));
-  EXPECT_TRUE(base::DeletePathRecursively(directory_.GetPath()));
-  EXPECT_FALSE(base::DirectoryExists(directory_.GetPath()));
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_fuzzer.cc b/content/browser/appcache/appcache_fuzzer.cc
deleted file mode 100644
index 1d68c049..0000000
--- a/content/browser/appcache/appcache_fuzzer.cc
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/i18n/icu_util.h"
-#include "base/macros.h"
-#include "base/no_destructor.h"
-#include "base/test/test_timeouts.h"
-#include "content/browser/appcache/appcache_fuzzer.pb.h"
-#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/test/test_content_browser_client.h"
-#include "content/test/test_content_client.h"
-#include "mojo/core/embedder/embedder.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/network/public/mojom/url_response_head.mojom.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "storage/browser/test/mock_special_storage_policy.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
-
-namespace content {
-
-namespace {
-
-struct Env {
-  Env()
-      : task_environment((base::CommandLine::Init(0, nullptr),
-                          TestTimeouts::Initialize(),
-                          base::test::TaskEnvironment::MainThreadType::IO)) {
-    logging::SetMinLogLevel(logging::LOG_FATAL);
-    mojo::core::Init();
-    test_content_client = std::make_unique<TestContentClient>();
-    test_content_browser_client = std::make_unique<TestContentBrowserClient>();
-    SetContentClient(test_content_client.get());
-    SetBrowserClientForTesting(test_content_browser_client.get());
-    CHECK(base::i18n::InitializeICU());
-
-    // Ensure the process ID that will be used for creating the appcache
-    // backend is registered with ChildProcessSecurityPolicy.  This avoids
-    // hitting DCHECKs that its associated
-    // ChildProcessSecurityPolicyImpl::Handle() is invalid.
-    ChildProcessSecurityPolicyImpl::GetInstance()->Add(kProcessId,
-                                                       &test_browser_context);
-  }
-
-  void InitializeAppCacheService(
-      network::TestURLLoaderFactory* mock_url_loader_factory) {
-    appcache_service = base::MakeRefCounted<ChromeAppCacheService>(
-        /*proxy=*/nullptr, /*partition=*/nullptr);
-
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&ChromeAppCacheService::Initialize, appcache_service,
-                       base::FilePath(), &test_browser_context,
-                       /*special_storage_policy=*/nullptr));
-    task_environment.RunUntilIdle();
-  }
-
-  BrowserTaskEnvironment task_environment;
-  scoped_refptr<ChromeAppCacheService> appcache_service;
-  std::unique_ptr<TestContentClient> test_content_client;
-  std::unique_ptr<TestContentBrowserClient> test_content_browser_client;
-  TestBrowserContext test_browser_context;
-  const int kProcessId = 1;
-
-  // used by ICU integration.
-  base::AtExitManager at_exit_manager;
-};
-
-Env& SingletonEnv() {
-  static base::NoDestructor<Env> env;
-  return *env;
-}
-
-void HeadersToRaw(std::string* headers) {
-  std::replace(headers->begin(), headers->end(), '\n', '\0');
-  if (!headers->empty())
-    headers += '\0';
-}
-
-std::string GetUrl(const fuzzing::proto::Url& url) {
-  if (url.url_test_case_idx() == fuzzing::proto::EMPTY) {
-    return "";
-  }
-
-  return "http://localhost/" + std::to_string(url.url_test_case_idx());
-}
-
-std::string GetManifest(
-    const fuzzing::proto::ManifestResponse& manifest_response) {
-  std::string response = "CACHE MANIFEST\n";
-  for (const fuzzing::proto::Url& url : manifest_response.urls()) {
-    response += GetUrl(url) + "\n";
-  }
-  return response;
-}
-
-void DoRequest(network::TestURLLoaderFactory* factory,
-               const fuzzing::proto::Url& url,
-               uint32_t code,
-               bool do_not_cache,
-               const fuzzing::proto::ManifestResponse& manifest_response) {
-  network::URLLoaderCompletionStatus status;
-  status.error_code = net::OK;
-
-  auto response = network::mojom::URLResponseHead::New();
-
-  std::string headers = "HTTP/1.1 ";
-  headers += std::to_string(code);
-  headers += "\n";
-
-  if (do_not_cache) {
-    headers += "Cache-Control: no-cache, no-store, must-revalidate\n";
-    headers += "Pragma: no-cache\n";
-    headers += "Expires: 0\n";
-    headers += "DNT: 1\n";
-  }
-  HeadersToRaw(&headers);
-
-  response->headers = base::MakeRefCounted<net::HttpResponseHeaders>(headers);
-
-  // To simplify the fuzzer, we respond to all requests with a manifest.
-  // When we're performing a manifest fetch, this data will affect the
-  // control flow of the appcache code. Otherwise it's just treated like
-  // a blob of data.
-  std::string content = GetManifest(manifest_response);
-  content += "\n# ";
-
-  factory->SimulateResponseForPendingRequest(
-      GURL(GetUrl(url)), status, std::move(response), content,
-      network::TestURLLoaderFactory::kUrlMatchPrefix);
-}
-
-}  // anonymous namespace
-
-DEFINE_BINARY_PROTO_FUZZER(const fuzzing::proto::Session& session) {
-  network::TestURLLoaderFactory mock_url_loader_factory;
-  SingletonEnv().InitializeAppCacheService(&mock_url_loader_factory);
-
-  // Create a context for mojo::ReportBadMessage.
-  mojo::Message message;
-  auto dispatch_context =
-      std::make_unique<mojo::internal::MessageDispatchContext>(&message);
-
-  mojo::Remote<blink::mojom::AppCacheBackend> host;
-  SingletonEnv().appcache_service->CreateBackend(
-      SingletonEnv().kProcessId, /*routing_id=*/MSG_ROUTING_NONE,
-      host.BindNewPipeAndPassReceiver());
-
-  std::map<int, mojo::Remote<blink::mojom::AppCacheHost>> registered_hosts;
-  std::map<int, base::UnguessableToken> registered_host_ids_;
-  for (const fuzzing::proto::Command& command : session.commands()) {
-    switch (command.command_case()) {
-      case fuzzing::proto::Command::kRegisterHost: {
-        int32_t host_id = command.register_host().host_id();
-        auto& host_id_token = registered_host_ids_[host_id];
-        if (host_id_token.is_empty())
-          host_id_token = base::UnguessableToken::Create();
-        mojo::PendingRemote<blink::mojom::AppCacheFrontend> frontend;
-        ignore_result(frontend.InitWithNewPipeAndPassReceiver());
-        registered_hosts[host_id].reset();
-        host->RegisterHost(
-            registered_hosts[host_id].BindNewPipeAndPassReceiver(),
-            std::move(frontend), host_id_token);
-        break;
-      }
-      case fuzzing::proto::Command::kUnregisterHost: {
-        int32_t host_id = command.unregister_host().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-
-        registered_hosts.erase(host_it);
-        break;
-      }
-      case fuzzing::proto::Command::kSelectCache: {
-        int32_t host_id = command.select_cache().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        int32_t from_id = command.select_cache().from_id();
-        GURL document_url = GURL(GetUrl(command.select_cache().document_url()));
-        GURL opt_manifest_url =
-            GURL(GetUrl(command.select_cache().opt_manifest_url()));
-
-        host_it->second->SelectCache(document_url, from_id, opt_manifest_url);
-        break;
-      }
-      case fuzzing::proto::Command::kSetSpawningHostId: {
-        int32_t host_id = command.set_spawning_host_id().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        int32_t spawning_host_id =
-            command.set_spawning_host_id().spawning_host_id();
-        auto& spawning_host_id_token = registered_host_ids_[spawning_host_id];
-        if (spawning_host_id_token.is_empty())
-          spawning_host_id_token = base::UnguessableToken::Create();
-        host_it->second->SetSpawningHostId(spawning_host_id_token);
-        break;
-      }
-      case fuzzing::proto::Command::kSelectCacheForWorker: {
-        int32_t host_id = command.select_cache_for_worker().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        int64_t cache_document_was_loaded_from =
-            command.select_cache_for_worker().cache_document_was_loaded_from();
-        host_it->second->SelectCacheForWorker(cache_document_was_loaded_from);
-        break;
-      }
-      case fuzzing::proto::Command::kMarkAsForeignEntry: {
-        int32_t host_id = command.mark_as_foreign_entry().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        GURL url(GetUrl(command.mark_as_foreign_entry().document_url()));
-        int64_t cache_document_was_loaded_from =
-            command.mark_as_foreign_entry().cache_document_was_loaded_from();
-        host_it->second->MarkAsForeignEntry(url,
-                                            cache_document_was_loaded_from);
-        break;
-      }
-      case fuzzing::proto::Command::kGetStatus: {
-        int32_t host_id = command.get_status().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        host_it->second->GetStatus(base::DoNothing());
-        break;
-      }
-      case fuzzing::proto::Command::kStartUpdate: {
-        int32_t host_id = command.start_update().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        host_it->second->StartUpdate(base::DoNothing());
-        break;
-      }
-      case fuzzing::proto::Command::kSwapCache: {
-        int32_t host_id = command.swap_cache().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        host_it->second->SwapCache(base::DoNothing());
-        break;
-      }
-      case fuzzing::proto::Command::kGetResourceList: {
-        int32_t host_id = command.get_resource_list().host_id();
-        auto host_it = registered_hosts.find(host_id);
-        if (host_it == registered_hosts.end())
-          break;
-        host_it->second->GetResourceList(base::DoNothing());
-        break;
-      }
-      case fuzzing::proto::Command::kDoRequest: {
-        uint32_t code = command.do_request().http_code();
-        bool do_not_cache = command.do_request().do_not_cache();
-        const fuzzing::proto::ManifestResponse& manifest_response =
-            command.do_request().manifest_response();
-        DoRequest(&mock_url_loader_factory, command.do_request().url(), code,
-                  do_not_cache, manifest_response);
-        break;
-      }
-      case fuzzing::proto::Command::kRunUntilIdle: {
-        SingletonEnv().task_environment.RunUntilIdle();
-        break;
-      }
-      case fuzzing::proto::Command::COMMAND_NOT_SET: {
-        break;
-      }
-    }
-  }
-
-  host.reset();
-  // TODO(nedwilliamson): Investigate removing this or reinitializing
-  // the appcache service as a fuzzer command.
-  SingletonEnv().task_environment.RunUntilIdle();
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_fuzzer.proto b/content/browser/appcache/appcache_fuzzer.proto
deleted file mode 100644
index 6f7dfda..0000000
--- a/content/browser/appcache/appcache_fuzzer.proto
+++ /dev/null
@@ -1,156 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-syntax = "proto2";
-
-package content.fuzzing.proto;
-
-message Session {
-  repeated Command commands = 1;
-}
-
-// Based on blink::mojom::AppCacheBackend and blink::mojom::AppCacheHost
-// interfaces.
-// See third_party/blink/public/mojom/appcache/appcache.mojom
-message Command {
-  oneof command {
-    RegisterHost register_host = 1;
-    UnregisterHost unregister_host = 2;
-    SelectCache select_cache = 3;
-    SetSpawningHostId set_spawning_host_id = 4;
-    SelectCacheForWorker select_cache_for_worker = 5;
-    MarkAsForeignEntry mark_as_foreign_entry = 6;
-    GetStatus get_status = 7;
-    StartUpdate start_update = 8;
-    SwapCache swap_cache = 9;
-    GetResourceList get_resource_list = 10;
-    DoRequest do_request = 11;
-    RunUntilIdle run_until_idle = 12;
-  }
-}
-
-// We only need a few hosts to encapsulate all the logic
-enum HostId {
-  HOST_N2 = -2;
-  HOST_N1 = -1;
-  HOST_0 = 0;
-  HOST_1 = 1;
-  HOST_2 = 2;
-}
-
-// Caches are created more quickly so we want more of them
-enum CacheId {
-  CACHE_N1 = -1;
-  CACHE_0 = 0;
-  CACHE_1 = 1;
-  CACHE_2 = 2;
-  CACHE_3 = 3;
-  CACHE_4 = 4;
-  CACHE_5 = 5;
-  CACHE_6 = 6;
-  CACHE_7 = 7;
-  CACHE_8 = 8;
-  CACHE_9 = 9;
-}
-
-message RegisterHost {
-  required HostId host_id = 1;
-}
-
-message UnregisterHost {
-  required HostId host_id = 1;
-}
-
-message SelectCache {
-  required HostId host_id = 1;
-  required HostId from_id = 2;
-  required Url document_url = 3;
-  required Url opt_manifest_url = 4;
-}
-
-enum HttpCode {
-  RESPONSE_100 = 100;
-  RESPONSE_200 = 200;
-  RESPONSE_206 = 206;
-  RESPONSE_301 = 301;
-  RESPONSE_302 = 302;
-  RESPONSE_303 = 303;
-  RESPONSE_304 = 304;
-  RESPONSE_307 = 307;
-  RESPONSE_308 = 308;
-  RESPONSE_401 = 401;
-  RESPONSE_403 = 403;
-  RESPONSE_404 = 404;
-  RESPONSE_500 = 500;
-  RESPONSE_501 = 501;
-}
-
-message DoRequest {
-  required HttpCode http_code = 1;
-  required bool do_not_cache = 2;
-  required ManifestResponse manifest_response = 3;
-  required Url url = 4;
-}
-
-message ManifestResponse {
-  repeated Url urls = 1;
-}
-
-// Make sure to test logic when fetching more than the max concurrent allowed.
-enum UrlTestCaseIndex {
-  EMPTY = 0;
-  PATH_1 = 1;
-  PATH_2 = 2;
-  PATH_3 = 3;
-  PATH_4 = 4;
-  PATH_5 = 5;
-}
-
-// In order to efficiently fuzz the appcache logic, we don't want
-// to worry about all the possible url parsing. For this reason,
-// we generate either an empty GURL or one of up to 5 paths,
-// http://localhost/[1-5]. We can update this if in the future
-// more coverage can be achieved.
-// We represent this with a UrlTestCaseIndex enum. The 0 value is
-// a special case representing an empty string or GURL().
-// If not empty, we just append the int value of the UrlTestCaseIndex
-// enum to "http://localhost/". Using an enum in this way makes
-// mutations more efficient.
-message Url {
-  required UrlTestCaseIndex url_test_case_idx = 1;
-}
-
-message RunUntilIdle {}
-
-message SetSpawningHostId {
-  required HostId host_id = 1;
-  required HostId spawning_host_id = 2;
-}
-
-message SelectCacheForWorker {
-  required HostId host_id = 1;
-  required CacheId cache_document_was_loaded_from = 2;
-}
-
-message MarkAsForeignEntry {
-  required HostId host_id = 1;
-  required Url document_url = 2;
-  required CacheId cache_document_was_loaded_from = 3;
-}
-
-message GetStatus {
-  required HostId host_id = 1;
-}
-
-message StartUpdate {
-  required HostId host_id = 1;
-}
-
-message SwapCache {
-  required HostId host_id = 1;
-}
-
-message GetResourceList {
-  required HostId host_id = 1;
-}
diff --git a/content/browser/appcache/appcache_group_unittest.cc b/content/browser/appcache/appcache_group_unittest.cc
deleted file mode 100644
index 60b2e1f..0000000
--- a/content/browser/appcache/appcache_group_unittest.cc
+++ /dev/null
@@ -1,331 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <string>
-
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_host.h"
-#include "content/browser/appcache/appcache_update_job.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-
-namespace {
-
-class TestAppCacheFrontend : public blink::mojom::AppCacheFrontend {
- public:
-  TestAppCacheFrontend()
-      : last_cache_id_(-1),
-        last_status_(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE) {}
-
-  void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {
-    last_host_id_ = receivers_.current_context();
-    last_cache_id_ = info->cache_id;
-    last_status_ = info->status;
-  }
-
-  void EventRaised(blink::mojom::AppCacheEventID event_id) override {}
-
-  void ErrorEventRaised(
-      blink::mojom::AppCacheErrorDetailsPtr details) override {}
-
-  void ProgressEventRaised(const GURL& url,
-                           int32_t num_total,
-                           int32_t num_complete) override {}
-
-  void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
-                  const std::string& message) override {}
-
-  void SetSubresourceFactory(
-      mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory)
-      override {}
-
-  mojo::PendingRemote<blink::mojom::AppCacheFrontend> Bind(
-      const base::UnguessableToken& host_id) {
-    mojo::PendingRemote<blink::mojom::AppCacheFrontend> result;
-    receivers_.Add(this, result.InitWithNewPipeAndPassReceiver(), host_id);
-    return result;
-  }
-
-  base::UnguessableToken last_host_id_;
-  int64_t last_cache_id_;
-  blink::mojom::AppCacheStatus last_status_;
-  mojo::ReceiverSet<blink::mojom::AppCacheFrontend, base::UnguessableToken>
-      receivers_;
-};
-
-}  // namespace
-
-namespace content {
-
-class TestUpdateObserver : public AppCacheGroup::UpdateObserver {
- public:
-  TestUpdateObserver() : update_completed_(false), group_has_cache_(false) {}
-
-  void OnUpdateComplete(AppCacheGroup* group) override {
-    update_completed_ = true;
-    group_has_cache_ = group->HasCache();
-  }
-
-  virtual void OnContentBlocked(AppCacheGroup* group) {}
-
-  bool update_completed_;
-  bool group_has_cache_;
-};
-
-class TestAppCacheHost : public AppCacheHost {
- public:
-  TestAppCacheHost(const base::UnguessableToken& host_id,
-                   TestAppCacheFrontend* frontend,
-                   AppCacheServiceImpl* service)
-      : AppCacheHost(
-            host_id,
-            /*process_id=*/456,
-            /*render_frame_id=*/789,
-            ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                /*process_id=*/456),
-            frontend->Bind(host_id),
-            service),
-        update_completed_(false) {}
-
-  void OnUpdateComplete(AppCacheGroup* group) override {
-    update_completed_ = true;
-  }
-
-  bool update_completed_;
-};
-
-class AppCacheGroupTest : public testing::Test {
- private:
-  BrowserTaskEnvironment task_environment_;
-};
-
-TEST_F(AppCacheGroupTest, AddRemoveCache) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   GURL("http://foo.com"), 111);
-
-  base::Time now = base::Time::Now();
-
-  auto cache1 = base::MakeRefCounted<AppCache>(service.storage(), 111);
-  cache1->set_complete(true);
-  cache1->set_update_time(now);
-  group->AddCache(cache1.get());
-  EXPECT_EQ(cache1.get(), group->newest_complete_cache());
-
-  // Adding older cache does not change newest complete cache.
-  auto cache2 = base::MakeRefCounted<AppCache>(service.storage(), 222);
-  cache2->set_complete(true);
-  cache2->set_update_time(now - base::TimeDelta::FromDays(1));
-  group->AddCache(cache2.get());
-  EXPECT_EQ(cache1.get(), group->newest_complete_cache());
-
-  // Adding newer cache does change newest complete cache.
-  auto cache3 = base::MakeRefCounted<AppCache>(service.storage(), 333);
-  cache3->set_complete(true);
-  cache3->set_update_time(now + base::TimeDelta::FromDays(1));
-  group->AddCache(cache3.get());
-  EXPECT_EQ(cache3.get(), group->newest_complete_cache());
-
-  // Adding cache with same update time uses one with larger ID.
-  auto cache4 = base::MakeRefCounted<AppCache>(service.storage(), 444);
-  cache4->set_complete(true);
-  cache4->set_update_time(now + base::TimeDelta::FromDays(1));  // same as 3
-  group->AddCache(cache4.get());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());
-
-  // smaller id
-  auto cache5 = base::MakeRefCounted<AppCache>(service.storage(), 55);
-  cache5->set_complete(true);
-  cache5->set_update_time(now + base::TimeDelta::FromDays(1));  // same as 4
-  group->AddCache(cache5.get());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());  // no change
-
-  // Old caches can always be removed.
-  group->RemoveCache(cache1.get());
-  EXPECT_FALSE(cache1->owning_group());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());  // newest unchanged
-
-  // Remove rest of caches.
-  group->RemoveCache(cache2.get());
-  EXPECT_FALSE(cache2->owning_group());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());  // newest unchanged
-  group->RemoveCache(cache3.get());
-  EXPECT_FALSE(cache3->owning_group());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());  // newest unchanged
-  group->RemoveCache(cache5.get());
-  EXPECT_FALSE(cache5->owning_group());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());  // newest unchanged
-  group->RemoveCache(cache4.get());                         // newest removed
-  EXPECT_FALSE(cache4->owning_group());
-  EXPECT_FALSE(group->newest_complete_cache());  // no more newest cache
-
-  // Can remove newest cache if there are older caches.
-  group->AddCache(cache1.get());
-  EXPECT_EQ(cache1.get(), group->newest_complete_cache());
-  group->AddCache(cache4.get());
-  EXPECT_EQ(cache4.get(), group->newest_complete_cache());
-  group->RemoveCache(cache4.get());  // remove newest
-  EXPECT_FALSE(cache4->owning_group());
-  EXPECT_FALSE(group->newest_complete_cache());  // newest removed
-}
-
-TEST_F(AppCacheGroupTest, CleanupUnusedGroup) {
-  MockAppCacheService service;
-  TestAppCacheFrontend frontend;
-  AppCacheGroup* group =
-      new AppCacheGroup(service.storage(), GURL("http://foo.com"), 111);
-
-  auto host1_id = base::UnguessableToken::Create();
-  const int kMockProcessId1 = 1;
-  const int kMockProcessId2 = 2;
-  AppCacheHost host1(
-      host1_id, kMockProcessId1, /*render_frame_id=*/1,
-      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-          kMockProcessId1),
-      frontend.Bind(host1_id), &service);
-  auto host2_id = base::UnguessableToken::Create();
-  AppCacheHost host2(
-      host2_id, kMockProcessId2, /*render_frame_id=*/2,
-      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-          kMockProcessId2),
-      frontend.Bind(host2_id), &service);
-
-  base::Time now = base::Time::Now();
-
-  AppCache* cache1 = new AppCache(service.storage(), 111);
-  cache1->set_complete(true);
-  cache1->set_update_time(now);
-  group->AddCache(cache1);
-  EXPECT_EQ(cache1, group->newest_complete_cache());
-
-  host1.AssociateCompleteCache(cache1);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(frontend.last_host_id_, host1.host_id());
-  EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id());
-  EXPECT_EQ(frontend.last_status_,
-            blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE);
-
-  host2.AssociateCompleteCache(cache1);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(frontend.last_host_id_, host2.host_id());
-  EXPECT_EQ(frontend.last_cache_id_, cache1->cache_id());
-  EXPECT_EQ(frontend.last_status_,
-            blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE);
-
-  AppCache* cache2 = new AppCache(service.storage(), 222);
-  cache2->set_complete(true);
-  cache2->set_update_time(now + base::TimeDelta::FromDays(1));
-  group->AddCache(cache2);
-  EXPECT_EQ(cache2, group->newest_complete_cache());
-
-  // Unassociate all hosts from older cache.
-  host1.AssociateNoCache(GURL());
-  host2.AssociateNoCache(GURL());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(frontend.last_host_id_, host2.host_id());
-  EXPECT_EQ(frontend.last_cache_id_, blink::mojom::kAppCacheNoCacheId);
-  EXPECT_EQ(frontend.last_status_,
-            blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED);
-}
-
-TEST_F(AppCacheGroupTest, StartUpdate) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   GURL("http://foo.com"), 111);
-
-  // Set state to checking to prevent update job from executing fetches.
-  group->update_status_ = AppCacheGroup::CHECKING;
-  group->StartUpdate();
-  AppCacheUpdateJob* update = group->update_job_;
-  EXPECT_TRUE(update != nullptr);
-
-  // Start another update, check that same update job is in use.
-  group->StartUpdateWithHost(nullptr);
-  EXPECT_EQ(update, group->update_job_);
-
-  // Deleting the update should restore the group to AppCacheGroup::IDLE.
-  delete update;
-  EXPECT_TRUE(group->update_job_ == nullptr);
-  EXPECT_EQ(AppCacheGroup::IDLE, group->update_status());
-}
-
-TEST_F(AppCacheGroupTest, CancelUpdate) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   GURL("http://foo.com"), 111);
-
-  // Set state to checking to prevent update job from executing fetches.
-  group->update_status_ = AppCacheGroup::CHECKING;
-  group->StartUpdate();
-  AppCacheUpdateJob* update = group->update_job_;
-  EXPECT_TRUE(update != nullptr);
-
-  // Deleting the group should cancel the update.
-  TestUpdateObserver observer;
-  group->AddUpdateObserver(&observer);
-  group = nullptr;  // causes group to be deleted
-  EXPECT_TRUE(observer.update_completed_);
-  EXPECT_FALSE(observer.group_has_cache_);
-}
-
-TEST_F(AppCacheGroupTest, QueueUpdate) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   GURL("http://foo.com"), 111);
-
-  // Set state to checking to prevent update job from executing fetches.
-  group->update_status_ = AppCacheGroup::CHECKING;
-  group->StartUpdate();
-  EXPECT_TRUE(group->update_job_);
-
-  // Pretend group's update job is terminating so that next update is queued.
-  group->update_job_->internal_state_ =
-      AppCacheUpdateJobState::REFETCH_MANIFEST;
-  EXPECT_TRUE(group->update_job_->IsTerminating());
-
-  TestAppCacheFrontend frontend;
-  TestAppCacheHost host(base::UnguessableToken::Create(), &frontend, &service);
-  host.new_master_entry_url_ = GURL("http://foo.com/bar.txt");
-  group->StartUpdateWithNewMasterEntry(&host, host.new_master_entry_url_);
-  EXPECT_FALSE(group->queued_updates_.empty());
-
-  group->AddUpdateObserver(&host);
-  EXPECT_FALSE(group->FindObserver(&host, group->observers_));
-  EXPECT_TRUE(group->FindObserver(&host, group->queued_observers_));
-
-  // Delete update to cause it to complete. Verify no update complete notice
-  // sent to host.
-  delete group->update_job_;
-  EXPECT_EQ(AppCacheGroup::IDLE, group->update_status_);
-  EXPECT_FALSE(group->restart_update_task_.IsCancelled());
-  EXPECT_FALSE(host.update_completed_);
-
-  // Start another update. Cancels task and will run queued updates.
-  group->update_status_ = AppCacheGroup::CHECKING;  // prevent actual fetches
-  group->StartUpdate();
-  EXPECT_TRUE(group->update_job_);
-  EXPECT_TRUE(group->restart_update_task_.IsCancelled());
-  EXPECT_TRUE(group->queued_updates_.empty());
-  EXPECT_FALSE(group->update_job_->pending_master_entries_.empty());
-  EXPECT_FALSE(group->FindObserver(&host, group->queued_observers_));
-  EXPECT_TRUE(group->FindObserver(&host, group->observers_));
-
-  // Delete update to cause it to complete. Verify host is notified.
-  delete group->update_job_;
-  EXPECT_EQ(AppCacheGroup::IDLE, group->update_status_);
-  EXPECT_TRUE(group->restart_update_task_.IsCancelled());
-  EXPECT_TRUE(host.update_completed_);
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_host_unittest.cc b/content/browser/appcache/appcache_host_unittest.cc
deleted file mode 100644
index d0c0d75..0000000
--- a/content/browser/appcache/appcache_host_unittest.cc
+++ /dev/null
@@ -1,857 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_host.h"
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/test/task_environment.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_backend_impl.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_request_handler.h"
-#include "content/browser/appcache/mock_appcache_policy.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/isolation_context.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_renderer_host.h"
-#include "content/test/test_web_contents.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/test_support/test_utils.h"
-#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_manager.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/storage_key/storage_key.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-#include "url/origin.h"
-
-namespace content {
-
-namespace {
-const int64_t kUnsetCacheId = -222;
-}  // namespace
-
-class AppCacheHostTest : public testing::Test {
- public:
-  AppCacheHostTest()
-      : web_contents_(TestWebContents::Create(&browser_context_, nullptr)),
-        kProcessIdForTest(web_contents_->GetMainFrame()->GetProcess()->GetID()),
-        kRenderFrameIdForTest(web_contents_->GetMainFrame()->GetRoutingID()),
-        mock_frontend_(web_contents_.get()) {
-    get_status_callback_ = base::BindRepeating(
-        &AppCacheHostTest::GetStatusCallback, base::Unretained(this));
-    AppCacheRequestHandler::SetRunningInTests(true);
-  }
-
-  ~AppCacheHostTest() override {
-    AppCacheRequestHandler::SetRunningInTests(false);
-  }
-
-  class MockFrontend : public blink::mojom::AppCacheFrontend,
-                       public WebContentsObserver {
-   public:
-    explicit MockFrontend(WebContents* web_contents)
-        : WebContentsObserver(web_contents),
-          last_cache_id_(kUnsetCacheId),
-          last_status_(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE),
-          last_event_id_(
-              blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT),
-          content_blocked_(false) {}
-
-    void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {
-      last_cache_id_ = info->cache_id;
-      last_status_ = info->status;
-    }
-
-    void EventRaised(blink::mojom::AppCacheEventID event_id) override {
-      last_event_id_ = event_id;
-    }
-
-    void ErrorEventRaised(
-        blink::mojom::AppCacheErrorDetailsPtr details) override {
-      last_event_id_ = blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT;
-    }
-
-    void ProgressEventRaised(const GURL& url,
-                             int32_t num_total,
-                             int32_t num_complete) override {
-      last_event_id_ = blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT;
-    }
-
-    void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
-                    const std::string& message) override {}
-
-    void SetSubresourceFactory(
-        mojo::PendingRemote<network::mojom::URLLoaderFactory>
-            url_loader_factory) override {}
-
-    // WebContentsObserver:
-    void AppCacheAccessed(const GURL& manifest_url,
-                          bool blocked_by_policy) override {
-      appcache_accessed_ = true;
-      if (blocked_by_policy)
-        content_blocked_ = true;
-    }
-
-    int64_t last_cache_id_;
-    blink::mojom::AppCacheStatus last_status_;
-    blink::mojom::AppCacheEventID last_event_id_;
-    bool content_blocked_;
-    bool appcache_accessed_ = false;
-  };
-
-  class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
-   public:
-    MockQuotaManagerProxy()
-        : QuotaManagerProxy(nullptr, base::SequencedTaskRunnerHandle::Get()) {}
-
-    // Not needed for our tests.
-    void RegisterClient(
-        mojo::PendingRemote<storage::mojom::QuotaClient> client,
-        storage::QuotaClientType client_type,
-        const std::vector<blink::mojom::StorageType>& storage_types) override {}
-    void NotifyStorageAccessed(const blink::StorageKey& storage_key,
-                               blink::mojom::StorageType type,
-                               base::Time access_time) override {}
-    void NotifyStorageModified(
-        storage::QuotaClientType client_id,
-        const blink::StorageKey& storage_key,
-        blink::mojom::StorageType type,
-        int64_t delta,
-        base::Time modification_time,
-        scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-        base::OnceClosure callback) override {
-      if (callback)
-        callback_task_runner->PostTask(FROM_HERE, std::move(callback));
-    }
-    void SetUsageCacheEnabled(storage::QuotaClientType client_id,
-                              const blink::StorageKey& storage_key,
-                              blink::mojom::StorageType type,
-                              bool enabled) override {}
-    void GetUsageAndQuota(
-        const blink::StorageKey& storage_key,
-        blink::mojom::StorageType type,
-        scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-        UsageAndQuotaCallback callback) override {}
-
-   protected:
-    ~MockQuotaManagerProxy() override = default;
-  };
-
-  void GetStatusCallback(blink::mojom::AppCacheStatus status) {
-    last_status_result_ = status;
-  }
-
-  void StartUpdateCallback(bool result) { last_start_result_ = result; }
-
-  void SwapCacheCallback(bool result) { last_swap_result_ = result; }
-
-  void LockProcessToURL(const GURL& url) {
-    ChildProcessSecurityPolicyImpl::GetInstance()->LockProcessForTesting(
-        web_contents_->GetMainFrame()->GetSiteInstance()->GetIsolationContext(),
-        kProcessIdForTest, url);
-  }
-
-  BrowserTaskEnvironment task_environment_;
-  RenderViewHostTestEnabler rvh_enabler_;
-  TestBrowserContext browser_context_;
-  std::unique_ptr<TestWebContents> web_contents_;
-
-  const int kProcessIdForTest;
-  const int kRenderFrameIdForTest;
-  const base::UnguessableToken kHostIdForTest =
-      base::UnguessableToken::Create();
-
-  // Mock classes for the 'host' to work with
-  MockAppCacheService service_;
-  MockFrontend mock_frontend_;
-
-  // Mock callbacks we expect to receive from the 'host'
-  blink::mojom::AppCacheHost::GetStatusCallback get_status_callback_;
-
-  blink::mojom::AppCacheStatus last_status_result_;
-  bool last_swap_result_;
-  bool last_start_result_;
-};
-
-TEST_F(AppCacheHostTest, Basic) {
-  // Construct a host and test what state it appears to be in.
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  EXPECT_EQ(kHostIdForTest, host.host_id());
-  EXPECT_EQ(kProcessIdForTest, host.process_id());
-  EXPECT_TRUE(host.security_policy_handle());
-  EXPECT_TRUE(host.security_policy_handle()->is_valid());
-  EXPECT_EQ(&service_, host.service());
-  EXPECT_EQ(nullptr, host.associated_cache());
-  EXPECT_FALSE(host.is_selection_pending());
-
-  // See that the callbacks are delivered immediately
-  // and respond as if there is no cache selected.
-  last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-  host.GetStatus(std::move(get_status_callback_));
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            last_status_result_);
-
-  last_start_result_ = true;
-  host.StartUpdate(base::BindOnce(&AppCacheHostTest::StartUpdateCallback,
-                                  base::Unretained(this)));
-  EXPECT_FALSE(last_start_result_);
-
-  last_swap_result_ = true;
-  host.SwapCache(base::BindOnce(&AppCacheHostTest::SwapCacheCallback,
-                                base::Unretained(this)));
-  EXPECT_FALSE(last_swap_result_);
-}
-
-TEST_F(AppCacheHostTest, SelectNoCache) {
-  // Lock process with |kInitialDocumentURL| so we can only accept URLs that
-  // generate the same lock as |kInitialDocumentURL|.
-  const GURL kInitialDocumentURL("http://whatever/document");
-  LockProcessToURL(kInitialDocumentURL);
-
-  const std::vector<GURL> kDocumentURLs = {
-      GURL("http://whatever/"),
-      GURL("blob:http://whatever/6f7dc725-2131-4f8b-85ed-4f43d175324e"),
-      GURL("about:blank"), GURL("about:srcdoc"),
-      GURL("blob:null/6f7dc725-2131-4f8b-85ed-4f43d175324e")};
-  for (const GURL& document_url : kDocumentURLs) {
-    scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
-        base::MakeRefCounted<MockQuotaManagerProxy>();
-    service_.set_quota_manager_proxy(mock_quota_proxy.get());
-
-    // Reset our mock frontend
-    mock_frontend_.last_cache_id_ = -333;
-    mock_frontend_.last_status_ =
-        blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-
-    const blink::StorageKey kStorageKey(url::Origin::Create(document_url));
-    {
-      AppCacheHost host(
-          kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kProcessIdForTest),
-          mojo::NullRemote(), &service_);
-      host.set_frontend_for_testing(&mock_frontend_);
-
-      {
-        mojo::test::BadMessageObserver bad_message_observer;
-        host.SelectCache(document_url, blink::mojom::kAppCacheNoCacheId,
-                         GURL());
-
-        base::RunLoop().RunUntilIdle();
-        EXPECT_FALSE(bad_message_observer.got_bad_message());
-      }
-
-      // We should have received an OnCacheSelected msg
-      EXPECT_EQ(blink::mojom::kAppCacheNoCacheId,
-                mock_frontend_.last_cache_id_);
-      EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-                mock_frontend_.last_status_);
-
-      // Otherwise, see that it respond as if there is no cache selected.
-      EXPECT_EQ(kHostIdForTest, host.host_id());
-      EXPECT_EQ(&service_, host.service());
-      EXPECT_EQ(nullptr, host.associated_cache());
-      EXPECT_FALSE(host.is_selection_pending());
-      EXPECT_TRUE(host.preferred_manifest_url().is_empty());
-    }
-    service_.set_quota_manager_proxy(nullptr);
-  }
-}
-
-TEST_F(AppCacheHostTest, ForeignEntry) {
-  // Reset our mock frontend
-  mock_frontend_.last_cache_id_ = -333;
-  mock_frontend_.last_status_ =
-      blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-
-  // Precondition, a cache with an entry that is not marked as foreign.
-  const int kCacheId = 22;
-  const GURL kDocumentURL("http://origin/document");
-  auto cache = base::MakeRefCounted<AppCache>(service_.storage(), kCacheId);
-  cache->AddEntry(kDocumentURL, AppCacheEntry(AppCacheEntry::EXPLICIT));
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  host.MarkAsForeignEntry(kDocumentURL, kCacheId);
-
-  // We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            mock_frontend_.last_status_);
-
-  // See that it respond as if there is no cache selected.
-  EXPECT_EQ(kHostIdForTest, host.host_id());
-  EXPECT_EQ(&service_, host.service());
-  EXPECT_EQ(nullptr, host.associated_cache());
-  EXPECT_FALSE(host.is_selection_pending());
-
-  // See that the entry was marked as foreign.
-  EXPECT_TRUE(cache->GetEntry(kDocumentURL)->IsForeign());
-}
-
-TEST_F(AppCacheHostTest, ForeignFallbackEntry) {
-  // Reset our mock frontend
-  mock_frontend_.last_cache_id_ = -333;
-  mock_frontend_.last_status_ =
-      blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-
-  // Precondition, a cache with a fallback entry that is not marked as foreign.
-  const int kCacheId = 22;
-  const GURL kFallbackURL("http://origin/fallback_resource");
-  scoped_refptr<AppCache> cache =
-      base::MakeRefCounted<AppCache>(service_.storage(), kCacheId);
-  cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK));
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  host.NotifyMainResourceIsNamespaceEntry(kFallbackURL);
-  host.MarkAsForeignEntry(GURL("http://origin/missing_document"), kCacheId);
-
-  // We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            mock_frontend_.last_status_);
-
-  // See that the fallback entry was marked as foreign.
-  EXPECT_TRUE(cache->GetEntry(kFallbackURL)->IsForeign());
-}
-
-TEST_F(AppCacheHostTest, FailedCacheLoad) {
-  // Reset our mock frontend
-  mock_frontend_.last_cache_id_ = -333;
-  mock_frontend_.last_status_ =
-      blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  EXPECT_FALSE(host.is_selection_pending());
-
-  const int kMockCacheId = 333;
-
-  // Put it in a state where we're waiting on a cache
-  // load prior to finishing cache selection.
-  host.pending_selected_cache_id_ = kMockCacheId;
-  EXPECT_TRUE(host.is_selection_pending());
-
-  // The callback should not occur until we finish cache selection.
-  last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-  host.GetStatus(std::move(get_status_callback_));
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
-            last_status_result_);
-
-  // Satisfy the load with NULL, a failure.
-  host.OnCacheLoaded(nullptr, kMockCacheId);
-
-  // Cache selection should have finished
-  EXPECT_FALSE(host.is_selection_pending());
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            mock_frontend_.last_status_);
-
-  // Callback should have fired upon completing the cache load too.
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            last_status_result_);
-}
-
-TEST_F(AppCacheHostTest, FailedGroupLoad) {
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-
-  const GURL kMockManifestUrl("http://foo.bar/baz");
-
-  // Put it in a state where we're waiting on a cache
-  // load prior to finishing cache selection.
-  host.pending_selected_manifest_url_ = kMockManifestUrl;
-  EXPECT_TRUE(host.is_selection_pending());
-
-  // The callback should not occur until we finish cache selection.
-  last_status_result_ = blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-  host.GetStatus(std::move(get_status_callback_));
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
-            last_status_result_);
-
-  // Satisfy the load will NULL, a failure.
-  host.OnGroupLoaded(nullptr, kMockManifestUrl);
-
-  // Cache selection should have finished
-  EXPECT_FALSE(host.is_selection_pending());
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            mock_frontend_.last_status_);
-
-  // Callback should have fired upon completing the group load.
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-            last_status_result_);
-}
-
-TEST_F(AppCacheHostTest, SetSwappableCache) {
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  host.SetSwappableCache(nullptr);
-  EXPECT_FALSE(host.swappable_cache_.get());
-
-  const GURL kGroup1ManifestUrl("http://bar.com");
-  scoped_refptr<AppCacheGroup> group1 = base::MakeRefCounted<AppCacheGroup>(
-      service_.storage(), kGroup1ManifestUrl, service_.storage()->NewGroupId());
-  host.SetSwappableCache(group1.get());
-  EXPECT_FALSE(host.swappable_cache_.get());
-
-  scoped_refptr<AppCache> cache1 =
-      base::MakeRefCounted<AppCache>(service_.storage(), 111);
-  cache1->set_complete(true);
-  group1->AddCache(cache1.get());
-  host.SetSwappableCache(group1.get());
-  EXPECT_EQ(cache1, host.swappable_cache_.get());
-
-  mock_frontend_.last_cache_id_ =
-      kUnsetCacheId;  // to verify we received OnCacheSelected
-
-  host.AssociateCompleteCache(cache1.get());
-  EXPECT_FALSE(host.swappable_cache_.get());  // was same as associated cache
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE,
-            host.GetStatusSync());
-  // verify OnCacheSelected was called
-  EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
-  EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE,
-            mock_frontend_.last_status_);
-
-  scoped_refptr<AppCache> cache2 =
-      base::MakeRefCounted<AppCache>(service_.storage(), 222);
-  cache2->set_complete(true);
-  group1->AddCache(cache2.get());
-  EXPECT_EQ(cache2.get(), host.swappable_cache_.get());  // updated to newest
-
-  const GURL kGroup2ManifestUrl("http://foo.com/");
-  scoped_refptr<AppCacheGroup> group2 = base::MakeRefCounted<AppCacheGroup>(
-      service_.storage(), kGroup2ManifestUrl, service_.storage()->NewGroupId());
-  scoped_refptr<AppCache> cache3 =
-      base::MakeRefCounted<AppCache>(service_.storage(), 333);
-  cache3->set_complete(true);
-  group2->AddCache(cache3.get());
-
-  scoped_refptr<AppCache> cache4 =
-      base::MakeRefCounted<AppCache>(service_.storage(), 444);
-  cache4->set_complete(true);
-  group2->AddCache(cache4.get());
-  EXPECT_EQ(cache2.get(), host.swappable_cache_.get());  // unchanged
-
-  cache1.reset();
-  cache2.reset();
-
-  host.AssociateCompleteCache(cache3.get());
-  EXPECT_EQ(cache4.get(),
-            host.swappable_cache_.get());  // newest cache in group2
-  EXPECT_FALSE(group1->HasCache());  // both caches in group1 have refcount 0
-
-  cache3.reset();
-  cache4.reset();
-
-  host.AssociateNoCache(kGroup1ManifestUrl);
-  EXPECT_FALSE(host.swappable_cache_.get());
-  EXPECT_FALSE(group2->HasCache());  // both caches in group2 have refcount 0
-
-  // Host adds reference to newest cache when an update is complete.
-  scoped_refptr<AppCache> cache5 =
-      base::MakeRefCounted<AppCache>(service_.storage(), 555);
-  cache5->set_complete(true);
-  group2->AddCache(cache5.get());
-  host.group_being_updated_ = group2;
-  host.OnUpdateComplete(group2.get());
-  EXPECT_FALSE(host.group_being_updated_.get());
-  EXPECT_EQ(cache5.get(), host.swappable_cache_.get());
-
-  group2->RemoveCache(cache5.get());
-  EXPECT_FALSE(group2->HasCache());
-  host.group_being_updated_ = group2;
-  host.OnUpdateComplete(group2.get());
-  EXPECT_FALSE(host.group_being_updated_.get());
-  EXPECT_FALSE(host.swappable_cache_.get());  // group2 had no newest cache
-}
-
-TEST_F(AppCacheHostTest, SelectCacheAllowed) {
-  scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
-      base::MakeRefCounted<MockQuotaManagerProxy>();
-  MockAppCachePolicy mock_appcache_policy;
-  mock_appcache_policy.can_create_return_value_ = true;
-  service_.set_quota_manager_proxy(mock_quota_proxy.get());
-  service_.set_appcache_policy(&mock_appcache_policy);
-
-  // Reset our mock frontend
-  mock_frontend_.last_cache_id_ = -333;
-  mock_frontend_.last_status_ =
-      blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-  mock_frontend_.last_event_id_ =
-      blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT;
-  mock_frontend_.content_blocked_ = false;
-  mock_frontend_.appcache_accessed_ = false;
-
-  const GURL kDocAndStorageKeyUrl("http://whatever/");
-  const blink::StorageKey kStorageKey(
-      url::Origin::Create(kDocAndStorageKeyUrl));
-  const GURL kManifestUrl("http://whatever/cache.manifest");
-  {
-    AppCacheHost host(
-        kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            kProcessIdForTest),
-        mojo::NullRemote(), &service_);
-    host.set_frontend_for_testing(&mock_frontend_);
-    host.SetSiteForCookiesForTesting(
-        net::SiteForCookies::FromUrl(kDocAndStorageKeyUrl));
-    host.SelectCache(kDocAndStorageKeyUrl, blink::mojom::kAppCacheNoCacheId,
-                     kManifestUrl);
-
-    // MockAppCacheService::LoadOrCreateGroup is asynchronous, so we shouldn't
-    // have received an OnCacheSelected msg yet.
-    EXPECT_EQ(-333, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
-              mock_frontend_.last_status_);
-    // No error events either
-    EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT,
-              mock_frontend_.last_event_id_);
-    EXPECT_FALSE(mock_frontend_.content_blocked_);
-
-    EXPECT_TRUE(host.is_selection_pending());
-
-    base::RunLoop().RunUntilIdle();
-    EXPECT_FALSE(mock_frontend_.content_blocked_);
-    EXPECT_TRUE(mock_frontend_.appcache_accessed_);
-  }
-  service_.set_quota_manager_proxy(nullptr);
-}
-
-TEST_F(AppCacheHostTest, SelectCacheBlocked) {
-  scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy =
-      base::MakeRefCounted<MockQuotaManagerProxy>();
-  MockAppCachePolicy mock_appcache_policy;
-  mock_appcache_policy.can_create_return_value_ = false;
-  service_.set_quota_manager_proxy(mock_quota_proxy.get());
-  service_.set_appcache_policy(&mock_appcache_policy);
-
-  // Reset our mock frontend
-  mock_frontend_.last_cache_id_ = -333;
-  mock_frontend_.last_status_ =
-      blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE;
-  mock_frontend_.last_event_id_ =
-      blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT;
-  mock_frontend_.content_blocked_ = false;
-  mock_frontend_.appcache_accessed_ = false;
-
-  const GURL kDocAndStorageKeyUrl(GURL("http://whatever/").GetOrigin());
-  const blink::StorageKey kStorageKey(
-      url::Origin::Create(kDocAndStorageKeyUrl));
-  const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
-  {
-    AppCacheHost host(
-        kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            kProcessIdForTest),
-        mojo::NullRemote(), &service_);
-    host.set_frontend_for_testing(&mock_frontend_);
-    host.SetSiteForCookiesForTesting(
-        net::SiteForCookies::FromUrl(kDocAndStorageKeyUrl));
-    host.SelectCache(kDocAndStorageKeyUrl, blink::mojom::kAppCacheNoCacheId,
-                     kManifestUrl);
-
-    // We should have received an OnCacheSelected msg
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-              mock_frontend_.last_status_);
-
-    // Also, an error event was raised
-    EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT,
-              mock_frontend_.last_event_id_);
-
-    // Otherwise, see that it respond as if there is no cache selected.
-    EXPECT_EQ(kHostIdForTest, host.host_id());
-    EXPECT_EQ(&service_, host.service());
-    EXPECT_EQ(nullptr, host.associated_cache());
-    EXPECT_FALSE(host.is_selection_pending());
-    EXPECT_TRUE(host.preferred_manifest_url().is_empty());
-
-    base::RunLoop().RunUntilIdle();
-    EXPECT_TRUE(mock_frontend_.content_blocked_);
-    EXPECT_TRUE(mock_frontend_.appcache_accessed_);
-  }
-  service_.set_quota_manager_proxy(nullptr);
-}
-
-TEST_F(AppCacheHostTest, SelectCacheTwice) {
-  const GURL kDocAndStorageKeyUrl(GURL("http://whatever/").GetOrigin());
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(kDocAndStorageKeyUrl,
-                             blink::mojom::kAppCacheNoCacheId, GURL());
-
-    base::RunLoop().RunUntilIdle();
-    EXPECT_FALSE(bad_message_observer.got_bad_message());
-  }
-
-  // Select methods should bail if cache has already been selected.
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(kDocAndStorageKeyUrl,
-                             blink::mojom::kAppCacheNoCacheId, GURL());
-    EXPECT_EQ("ACH_SELECT_CACHE", bad_message_observer.WaitForBadMessage());
-  }
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCacheForWorker(blink::mojom::kAppCacheNoCacheId);
-    EXPECT_EQ("ACH_SELECT_CACHE_FOR_WORKER",
-              bad_message_observer.WaitForBadMessage());
-  }
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->MarkAsForeignEntry(kDocAndStorageKeyUrl,
-                                    blink::mojom::kAppCacheNoCacheId);
-    EXPECT_EQ("ACH_MARK_AS_FOREIGN_ENTRY",
-              bad_message_observer.WaitForBadMessage());
-  }
-}
-
-TEST_F(AppCacheHostTest, SelectCacheInvalidCacheId) {
-  const GURL kDocAndStorageKeyUrl(GURL("http://whatever/").GetOrigin());
-
-  // A cache that the document wasn't actually loaded from. Trying to select it
-  // should cause a BadMessage.
-  const int kCacheId = 22;
-  const GURL kDocumentURL("http://origin/document");
-  auto cache = base::MakeRefCounted<AppCache>(service_.storage(), kCacheId);
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(kDocAndStorageKeyUrl, kCacheId, GURL());
-
-    EXPECT_EQ("ACH_SELECT_CACHE_ID_NOT_OWNED",
-              bad_message_observer.WaitForBadMessage());
-  }
-}
-
-TEST_F(AppCacheHostTest, SelectCacheURLsForWrongSite) {
-  // Lock process with |kInitialDocumentURL| so we can only accept URLs that
-  // generate the same lock as |kInitialDocumentURL|.
-  const GURL kInitialDocumentURL("http://foo.com/document");
-  LockProcessToURL(kInitialDocumentURL);
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  // Verify that a document URL from the wrong site triggers a bad message.
-  {
-    const GURL kWrongSiteDocumentURL("http://whatever/");
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(kWrongSiteDocumentURL,
-                             blink::mojom::kAppCacheNoCacheId, GURL());
-
-    EXPECT_EQ("ACH_SELECT_CACHE_DOCUMENT_URL_ACCESS_NOT_ALLOWED",
-              bad_message_observer.WaitForBadMessage());
-  }
-
-  // Verify that a document URL with an inner hostname from the wrong site
-  // triggers a bad message.
-  {
-    const GURL kDocumentURL = kInitialDocumentURL;
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(
-        kDocumentURL, blink::mojom::kAppCacheNoCacheId,
-        GURL("blob:http://whatever/6f7dc725-2131-4f8b-85ed-4f43d175324e"));
-
-    EXPECT_EQ("ACH_SELECT_CACHE_MANIFEST_URL_ACCESS_NOT_ALLOWED",
-              bad_message_observer.WaitForBadMessage());
-  }
-
-  // Verify that a manifest URL from the wrong site triggers a bad message.
-  {
-    const GURL kDocumentURL = kInitialDocumentURL;
-    const GURL kManifestURL("http://whatever/");
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->SelectCache(kDocumentURL, blink::mojom::kAppCacheNoCacheId,
-                             kManifestURL);
-
-    EXPECT_EQ("ACH_SELECT_CACHE_MANIFEST_URL_ACCESS_NOT_ALLOWED",
-              bad_message_observer.WaitForBadMessage());
-  }
-}
-
-TEST_F(AppCacheHostTest, ForeignEntryForWrongSite) {
-  // Lock process with |kInitialDocumentURL| so we can only accept URLs that
-  // generate the same lock as |kInitialDocumentURL|.
-  const GURL kInitialDocumentURL("http://foo.com");
-  LockProcessToURL(kInitialDocumentURL);
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  // Verify that a document URL from the wrong site triggers a bad message.
-  {
-    const GURL kWrongSiteDocumentURL("http://origin/document");
-    mojo::test::BadMessageObserver bad_message_observer;
-    host_remote->MarkAsForeignEntry(kWrongSiteDocumentURL,
-                                    blink::mojom::kAppCacheNoCacheId);
-    EXPECT_EQ("ACH_MARK_AS_FOREIGN_ENTRY_DOCUMENT_URL_ACCESS_NOT_ALLOWED",
-              bad_message_observer.WaitForBadMessage());
-  }
-}
-
-TEST_F(AppCacheHostTest, SelectCacheAfterProcessCleanup) {
-  // Lock process with |kDocumentURL| so we can only accept URLs that
-  // generate the same lock as |kDocumentURL|.
-  const GURL kDocumentURL("http://foo.com/document");
-  const GURL kManifestURL("http://foo.com/manifest");
-
-  auto* security_policy = ChildProcessSecurityPolicyImpl::GetInstance();
-  LockProcessToURL(kDocumentURL);
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  EXPECT_TRUE(security_policy->CanAccessDataForOrigin(
-      kProcessIdForTest, url::Origin::Create(kDocumentURL)));
-
-  // Destroy the WebContents so the process gets cleaned up.
-  web_contents_.reset();
-  base::RunLoop().RunUntilIdle();
-
-  // Since |host| for kProcessIdForTest is still alive, the corresponding
-  // SecurityState in ChildProcessSecurityPolicy should also be kept alive,
-  // allowing access for kDocumentURL.
-  EXPECT_TRUE(security_policy->CanAccessDataForOrigin(
-      kProcessIdForTest, url::Origin::Create(kDocumentURL)));
-
-  // Verify that the document and manifest URLs do not trigger a bad message.
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-
-    EXPECT_EQ(kUnsetCacheId, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
-              mock_frontend_.last_status_);
-
-    host_remote->SelectCache(kDocumentURL, blink::mojom::kAppCacheNoCacheId,
-                             kManifestURL);
-
-    // Run loop to allow the bad message code to run if a bad message was
-    // triggered.
-    base::RunLoop().RunUntilIdle();
-    EXPECT_FALSE(bad_message_observer.got_bad_message());
-
-    // Verify the frontend was still called.
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-              mock_frontend_.last_status_);
-  }
-}
-
-TEST_F(AppCacheHostTest, ForeignEntryAfterProcessCleanup) {
-  // Lock process with |kDocumentURL| so we can only accept URLs that
-  // generate the same lock as |kDocumentURL|.
-  const GURL kDocumentURL("http://foo.com/document");
-
-  auto* security_policy = ChildProcessSecurityPolicyImpl::GetInstance();
-  LockProcessToURL(kDocumentURL);
-
-  AppCacheHost host(kHostIdForTest, kProcessIdForTest, kRenderFrameIdForTest,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kProcessIdForTest),
-                    mojo::NullRemote(), &service_);
-  host.set_frontend_for_testing(&mock_frontend_);
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote;
-  host.BindReceiver(host_remote.BindNewPipeAndPassReceiver());
-
-  EXPECT_TRUE(security_policy->CanAccessDataForOrigin(
-      kProcessIdForTest, url::Origin::Create(kDocumentURL)));
-
-  // Destroy the WebContents so the process gets cleaned up.
-  web_contents_.reset();
-  base::RunLoop().RunUntilIdle();
-
-  // Since |host| for kProcessIdForTest is still alive, the corresponding
-  // SecurityState in ChildProcessSecurityPolicy should also be kept alive,
-  // allowing access for kDocumentURL.
-  EXPECT_TRUE(security_policy->CanAccessDataForOrigin(
-      kProcessIdForTest, url::Origin::Create(kDocumentURL)));
-
-  // Verify that a document URL does not trigger a bad message.
-  {
-    mojo::test::BadMessageObserver bad_message_observer;
-
-    EXPECT_EQ(kUnsetCacheId, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_OBSOLETE,
-              mock_frontend_.last_status_);
-
-    host_remote->MarkAsForeignEntry(kDocumentURL,
-                                    blink::mojom::kAppCacheNoCacheId);
-
-    // Run loop to allow the bad message code to run if a bad message was
-    // triggered.
-    base::RunLoop().RunUntilIdle();
-    EXPECT_FALSE(bad_message_observer.got_bad_message());
-
-    // Verify the frontend was still called.
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
-    EXPECT_EQ(blink::mojom::AppCacheStatus::APPCACHE_STATUS_UNCACHED,
-              mock_frontend_.last_status_);
-  }
-}
-}  // namespace content
diff --git a/content/browser/appcache/appcache_manifest_parser_unittest.cc b/content/browser/appcache/appcache_manifest_parser_unittest.cc
deleted file mode 100644
index 34550ea..0000000
--- a/content/browser/appcache/appcache_manifest_parser_unittest.cc
+++ /dev/null
@@ -1,825 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/test/gtest_util.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "content/browser/appcache/appcache_manifest_parser.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class AppCacheManifestParserTest : public testing::Test {
- private:
-  blink::ScopedTestOriginTrialPolicy origin_trial_policy_;
-};
-
-TEST_F(AppCacheManifestParserTest, NoData) {
-  const GURL url("http://localhost");
-  const std::string scope = url.GetWithoutFilename().path();
-  AppCacheManifest manifest;
-
-  EXPECT_FALSE(ParseManifest(
-      url, scope, "", 0, PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest));
-
-  manifest = AppCacheManifest();
-  EXPECT_FALSE(ParseManifest(url, scope, "CACHE MANIFEST\r", 0,  // Len is 0.
-                             PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                             manifest));
-}
-
-TEST_F(AppCacheManifestParserTest, CheckSignature) {
-  const GURL url("http://localhost");
-  const std::string scope = url.GetWithoutFilename().path();
-
-  const std::string kBadSignatures[] = {
-    "foo",
-    "CACHE MANIFEST;V2\r",          // not followed by whitespace
-    "CACHE MANIFEST#bad\r",         // no whitespace before comment
-    "cache manifest ",              // wrong case
-    "#CACHE MANIFEST\r",            // comment
-    "xCACHE MANIFEST\n",            // bad first char
-    " CACHE MANIFEST\r",            // begins with whitespace
-    "\xEF\xBE\xBF" "CACHE MANIFEST\r",  // bad UTF-8 BOM value
-  };
-
-  for (const std::string& bad_signature : kBadSignatures) {
-    AppCacheManifest manifest;
-    EXPECT_FALSE(
-        ParseManifest(url, scope, bad_signature.c_str(), bad_signature.length(),
-                      PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest));
-  }
-
-  const std::string kGoodSignatures[] = {
-    "CACHE MANIFEST",
-    "CACHE MANIFEST ",
-    "CACHE MANIFEST\r",
-    "CACHE MANIFEST\n",
-    "CACHE MANIFEST\r\n",
-    "CACHE MANIFEST\t# ignore me\r",
-    "CACHE MANIFEST ignore\r\n",
-    "CHROMIUM CACHE MANIFEST\r\n",
-    "\xEF\xBB\xBF" "CACHE MANIFEST \r\n",   // BOM present
-  };
-
-  for (const std::string& good_signature : kGoodSignatures) {
-    AppCacheManifest manifest;
-    EXPECT_TRUE(ParseManifest(
-        url, scope, good_signature.c_str(), good_signature.length(),
-        PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest));
-  }
-}
-
-TEST_F(AppCacheManifestParserTest, HeaderMetrics) {
-  const GURL url("http://localhost");
-  const std::string scope = url.GetWithoutFilename().path();
-
-  struct TestCase {
-    std::string manifest;
-    int expected_false_count;
-    int expected_true_count;
-  } test_cases[] = {
-      {"CACHE MANIFEST\r\n", 1, 0},
-      {"CHROMIUM CACHE MANIFEST\r\n", 0, 1},
-      {"CACHE MANIFEST#bad\r\n", 0, 0},
-  };
-
-  for (const auto& test_case : test_cases) {
-    AppCacheManifest manifest;
-    base::HistogramTester tester;
-
-    ParseManifest(url, scope, test_case.manifest.c_str(),
-                  test_case.manifest.length(),
-                  PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest);
-    tester.ExpectBucketCount("appcache.Manifest.ChromeHeader", 0,
-                             test_case.expected_false_count);
-    tester.ExpectBucketCount("appcache.Manifest.ChromeHeader", 1,
-                             test_case.expected_true_count);
-  }
-}
-
-TEST_F(AppCacheManifestParserTest, DangerousModeMetrics) {
-  const GURL url("http://localhost");
-  const std::string scope = url.GetWithoutFilename().path();
-
-  struct TestCase {
-    std::string manifest;
-    ParseMode parse_mode;
-    int expected_false_count;
-    int expected_true_count;
-  } test_cases[] = {
-      {"CACHE MANIFEST\r\n", PARSE_MANIFEST_PER_STANDARD, 1, 0},
-      {"CACHE MANIFEST\r\n", PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, 0, 1},
-      {"CACHE MANIFEST#bad\r\n", PARSE_MANIFEST_PER_STANDARD, 0, 0},
-      {"CACHE MANIFEST#bad\r\n", PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, 0,
-       0},
-  };
-
-  for (const auto& test_case : test_cases) {
-    AppCacheManifest manifest;
-    base::HistogramTester tester;
-
-    ParseManifest(url, scope, test_case.manifest.c_str(),
-                  test_case.manifest.length(), test_case.parse_mode, manifest);
-    tester.ExpectBucketCount("appcache.Manifest.DangerousMode", 0,
-                             test_case.expected_false_count);
-    tester.ExpectBucketCount("appcache.Manifest.DangerousMode", 1,
-                             test_case.expected_true_count);
-  }
-}
-
-TEST_F(AppCacheManifestParserTest, NoManifestUrl) {
-  base::HistogramTester tester;
-  AppCacheManifest manifest;
-  const std::string kData("CACHE MANIFEST\r"
-    "relative/tobase.com\r"
-    "http://absolute.com/addme.com");
-  const GURL kUrl;
-  const std::string kScope("/");
-  EXPECT_FALSE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                             PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                             manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_EQ(manifest.parser_version, -1);
-}
-
-TEST_F(AppCacheManifestParserTest, NoManifestScope) {
-  base::HistogramTester tester;
-  AppCacheManifest manifest;
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "relative/tobase.com\r"
-      "http://absolute.com/addme.com");
-  const GURL kUrl("http://localhost");
-  const std::string kScope;
-  EXPECT_FALSE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                             PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                             manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_EQ(manifest.parser_version, -1);
-}
-
-TEST_F(AppCacheManifestParserTest, NoManifestUrlAndScope) {
-  base::HistogramTester tester;
-  AppCacheManifest manifest;
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "relative/tobase.com\r"
-      "http://absolute.com/addme.com");
-  const GURL kUrl;
-  const std::string kScope;
-  EXPECT_FALSE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                             PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                             manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_EQ(manifest.parser_version, -1);
-}
-
-TEST_F(AppCacheManifestParserTest, SimpleManifest) {
-  base::HistogramTester tester;
-  AppCacheManifest manifest;
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "relative/tobase.com\r"
-      "http://absolute.com/addme.com");
-  const GURL kUrl("http://localhost");
-  const std::string kScope = "/";
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  const size_t kExpected = 2;
-  EXPECT_EQ(manifest.explicit_urls.size(), kExpected);
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_EQ(manifest.parser_version, 2);
-}
-
-TEST_F(AppCacheManifestParserTest, ExplicitUrls) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://www.foo.com");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "relative/one\r"
-    "# some comment\r"
-    "http://www.foo.com/two#strip\r\n"
-    "NETWORK:\r"
-    "  \t CACHE:\r"
-    "HTTP://www.diff.com/three\r"
-    "FALLBACK:\r"
-    " \t # another comment with leading whitespace\n"
-    "IGNORE:\r"
-    "http://www.foo.com/ignore\r"
-    "CACHE: \r"
-    "garbage:#!@\r"
-    "https://www.foo.com/diffscheme \t \r"
-    "  \t relative/four#stripme\n\r"
-    "*\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-  EXPECT_EQ(manifest.parser_version, 2);
-
-  std::unordered_set<std::string> urls = manifest.explicit_urls;
-  const size_t kExpected = 5;
-  ASSERT_EQ(kExpected, urls.size());
-  EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
-
-  // Wildcard is treated as a relative URL in explicit section.
-  EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
-
-  // We should get the same results with dangerous features disallowed.
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-
-  urls = manifest.explicit_urls;
-  ASSERT_EQ(kExpected, urls.size());
-  EXPECT_TRUE(urls.find("http://www.foo.com/relative/one") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.foo.com/two") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.diff.com/three") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.foo.com/relative/four") != urls.end());
-
-  // Wildcard is treated as a relative URL in explicit section.
-  EXPECT_TRUE(urls.find("http://www.foo.com/*") != urls.end());
-}
-
-TEST_F(AppCacheManifestParserTest, SafelistUrls) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://www.bar.com");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "NETWORK:\r"
-    "relative/one\r"
-    "# a comment\r"
-    "http://www.bar.com/two\r"
-    "HTTP://www.diff.com/three#strip\n\r"
-    "FALLBACK:\r"
-    "garbage\r"
-    "UNKNOWN:\r"
-    "http://www.bar.com/ignore\r"
-    "CACHE:\r"
-    "NETWORK:\r"
-    "https://www.wrongscheme.com\n"
-    "relative/four#stripref \t \r"
-    "http://www.five.com\r\n"
-    "*foo\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.intercept_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-
-  const std::vector<AppCacheNamespace>& online =
-      manifest.online_safelist_namespaces;
-  const size_t kExpected = 6;
-  ASSERT_EQ(kExpected, online.size());
-  EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE, online[0].type);
-  EXPECT_TRUE(online[0].target_url.is_empty());
-  EXPECT_EQ(GURL("http://www.bar.com/relative/one"), online[0].namespace_url);
-  EXPECT_EQ(GURL("http://www.bar.com/two"), online[1].namespace_url);
-  EXPECT_EQ(GURL("http://www.diff.com/three"), online[2].namespace_url);
-  EXPECT_EQ(GURL("http://www.bar.com/relative/four"), online[3].namespace_url);
-  EXPECT_EQ(GURL("http://www.five.com"), online[4].namespace_url);
-  EXPECT_EQ(GURL("http://www.bar.com/*foo"), online[5].namespace_url);
-}
-
-TEST_F(AppCacheManifestParserTest, FallbackUrls) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://glorp.com");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "# a comment\r"
-    "CACHE:\r"
-    "NETWORK:\r"
-    "UNKNOWN:\r"
-    "FALLBACK:\r"
-    "relative/one \t \t http://glorp.com/onefb  \t \r"
-    "*\r"
-    "https://glorp.com/wrong http://glorp.com/wrongfb\r"
-    "http://glorp.com/two#strip relative/twofb\r"
-    "HTTP://glorp.com/three relative/threefb#strip\n"
-    "http://glorp.com/three http://glorp.com/three-dup\r"
-    "http://glorp.com/solo \t \r\n"
-    "http://diff.com/ignore http://glorp.com/wronghost\r"
-    "http://glorp.com/wronghost http://diff.com/ohwell\r"
-    "relative/badscheme ftp://glorp.com/ignored\r"
-    "garbage\r\n"
-    "CACHE:\r"
-    "# only fallback urls in this test\r"
-    "FALLBACK:\n"
-    "relative/four#strip relative/fourfb#strip\r"
-    "http://www.glorp.com/notsame relative/skipped\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-
-  const std::vector<AppCacheNamespace>& fallbacks =
-      manifest.fallback_namespaces;
-  const size_t kExpected = 5;
-  ASSERT_EQ(kExpected, fallbacks.size());
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[3].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[4].type);
-  EXPECT_EQ(GURL("http://glorp.com/relative/one"),
-            fallbacks[0].namespace_url);
-  EXPECT_EQ(GURL("http://glorp.com/onefb"),
-            fallbacks[0].target_url);
-  EXPECT_EQ(GURL("http://glorp.com/two"),
-            fallbacks[1].namespace_url);
-  EXPECT_EQ(GURL("http://glorp.com/relative/twofb"),
-            fallbacks[1].target_url);
-  EXPECT_EQ(GURL("http://glorp.com/three"),
-            fallbacks[2].namespace_url);
-  EXPECT_EQ(GURL("http://glorp.com/relative/threefb"),
-            fallbacks[2].target_url);
-  EXPECT_EQ(GURL("http://glorp.com/three"),       // duplicates are stored
-            fallbacks[3].namespace_url);
-  EXPECT_EQ(GURL("http://glorp.com/three-dup"),
-            fallbacks[3].target_url);
-  EXPECT_EQ(GURL("http://glorp.com/relative/four"),
-            fallbacks[4].namespace_url);
-  EXPECT_EQ(GURL("http://glorp.com/relative/fourfb"),
-            fallbacks[4].target_url);
-  EXPECT_TRUE(manifest.intercept_namespaces.empty());
-
-  // Nothing should be ignored since all namespaces are in scope.
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-}
-
-TEST_F(AppCacheManifestParserTest, FallbackUrlsWithPort) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://www.portme.com:1234");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "FALLBACK:\r"
-    "http://www.portme.com:1234/one relative/onefb\r"
-    "HTTP://www.portme.com:9876/wrong http://www.portme.com:1234/ignore\r"
-    "http://www.portme.com:1234/stillwrong http://www.portme.com:42/boo\r"
-    "relative/two relative/twofb\r"
-    "http://www.portme.com:1234/three HTTP://www.portme.com:1234/threefb\r"
-    "http://www.portme.com/noport http://www.portme.com:1234/skipped\r"
-    "http://www.portme.com:1234/skipme http://www.portme.com/noport\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-
-  const std::vector<AppCacheNamespace>& fallbacks =
-      manifest.fallback_namespaces;
-  const size_t kExpected = 3;
-  ASSERT_EQ(kExpected, fallbacks.size());
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[2].type);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
-            fallbacks[0].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/onefb"),
-            fallbacks[0].target_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
-            fallbacks[1].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/twofb"),
-            fallbacks[1].target_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
-            fallbacks[2].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/threefb"),
-            fallbacks[2].target_url);
-  EXPECT_TRUE(manifest.intercept_namespaces.empty());
-
-  // Nothing should be ignored since all namespaces are in scope.
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-}
-
-TEST_F(AppCacheManifestParserTest, InterceptUrls) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://www.portme.com:1234");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CHROMIUM CACHE MANIFEST\r"
-    "CHROMIUM-INTERCEPT:\r"
-    "http://www.portme.com:1234/one return relative/int1\r"
-    "HTTP://www.portme.com:9/wrong return http://www.portme.com:1234/ignore\r"
-    "http://www.portme.com:1234/wrong return http://www.portme.com:9/boo\r"
-    "relative/two return relative/int2\r"
-    "relative/three wrong relative/threefb\r"
-    "http://www.portme.com:1234/three return HTTP://www.portme.com:1234/int3\r"
-    "http://www.portme.com/noport return http://www.portme.com:1234/skipped\r"
-    "http://www.portme.com:1234/skipme return http://www.portme.com/noport\r"
-    "relative/wrong/again missing/intercept_type\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_FALSE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-
-  const std::vector<AppCacheNamespace>& intercepts =
-      manifest.intercept_namespaces;
-  const size_t kExpected = 3;
-  ASSERT_EQ(kExpected, intercepts.size());
-  EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[0].type);
-  EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[1].type);
-  EXPECT_EQ(APPCACHE_INTERCEPT_NAMESPACE, intercepts[2].type);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/one"),
-            intercepts[0].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int1"),
-            intercepts[0].target_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/two"),
-            intercepts[1].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/relative/int2"),
-            intercepts[1].target_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/three"),
-            intercepts[2].namespace_url);
-  EXPECT_EQ(GURL("http://www.portme.com:1234/int3"),
-            intercepts[2].target_url);
-
-  // Disallow intercepts this time.
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.explicit_urls.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-  EXPECT_TRUE(manifest.intercept_namespaces.empty());
-  EXPECT_FALSE(manifest.online_safelist_all);
-  EXPECT_TRUE(manifest.did_ignore_intercept_namespaces);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-}
-
-TEST_F(AppCacheManifestParserTest, ComboUrls) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://combo.com:42");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "relative/explicit-1\r"
-      "# some comment\r"
-      "http://combo.com:99/explicit-2#strip\r"
-      "NETWORK:\r"
-      "http://combo.com/safelist-1\r"
-      "HTTP://www.diff.com/safelist-2#strip\r"
-      "*\r"
-      "CACHE:\n\r"
-      "http://www.diff.com/explicit-3\r"
-      "FALLBACK:\r"
-      "http://combo.com:42/fallback-1 http://combo.com:42/fallback-1b\r"
-      "relative/fallback-2 relative/fallback-2b\r"
-      "UNKNOWN:\r\n"
-      "http://combo.com/ignoreme\r"
-      "relative/still-ignored\r"
-      "NETWORK:\r\n"
-      "relative/safelist-3#strip\r"
-      "http://combo.com:99/safelist-4\r");
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.online_safelist_all);
-
-  std::unordered_set<std::string> urls = manifest.explicit_urls;
-  size_t expected = 3;
-  ASSERT_EQ(expected, urls.size());
-  EXPECT_TRUE(urls.find("http://combo.com:42/relative/explicit-1") !=
-              urls.end());
-  EXPECT_TRUE(urls.find("http://combo.com:99/explicit-2") != urls.end());
-  EXPECT_TRUE(urls.find("http://www.diff.com/explicit-3") != urls.end());
-
-  const std::vector<AppCacheNamespace>& online =
-      manifest.online_safelist_namespaces;
-  expected = 4;
-  ASSERT_EQ(expected, online.size());
-  EXPECT_EQ(GURL("http://combo.com/safelist-1"), online[0].namespace_url);
-  EXPECT_EQ(GURL("http://www.diff.com/safelist-2"), online[1].namespace_url);
-  EXPECT_EQ(GURL("http://combo.com:42/relative/safelist-3"),
-            online[2].namespace_url);
-  EXPECT_EQ(GURL("http://combo.com:99/safelist-4"), online[3].namespace_url);
-
-  const std::vector<AppCacheNamespace>& fallbacks =
-      manifest.fallback_namespaces;
-  expected = 2;
-  ASSERT_EQ(expected, fallbacks.size());
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[0].type);
-  EXPECT_EQ(APPCACHE_FALLBACK_NAMESPACE, fallbacks[1].type);
-  EXPECT_EQ(GURL("http://combo.com:42/fallback-1"),
-            fallbacks[0].namespace_url);
-  EXPECT_EQ(GURL("http://combo.com:42/fallback-1b"),
-            fallbacks[0].target_url);
-  EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2"),
-            fallbacks[1].namespace_url);
-  EXPECT_EQ(GURL("http://combo.com:42/relative/fallback-2b"),
-            fallbacks[1].target_url);
-
-  EXPECT_TRUE(manifest.intercept_namespaces.empty());
-}
-
-TEST_F(AppCacheManifestParserTest, UnusualUtf8) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://bad.com");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "\xC0" "invalidutf8\r"
-    "nonbmp" "\xF1\x84\xAB\xBC\r");
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  std::unordered_set<std::string> urls = manifest.explicit_urls;
-  EXPECT_TRUE(urls.find("http://bad.com/%EF%BF%BDinvalidutf8") != urls.end())
-      << "manifest byte stream was passed through, not UTF-8-decoded";
-  EXPECT_TRUE(urls.find("http://bad.com/nonbmp%F1%84%AB%BC") != urls.end());
-}
-
-TEST_F(AppCacheManifestParserTest, IgnoreAfterSpace) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://smorg.borg");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData(
-    "CACHE MANIFEST\r"
-    "resource.txt this stuff after the white space should be ignored\r");
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-
-  std::unordered_set<std::string> urls = manifest.explicit_urls;
-  EXPECT_TRUE(urls.find("http://smorg.borg/resource.txt") != urls.end());
-}
-
-TEST_F(AppCacheManifestParserTest, DifferentOriginUrlWithSecureScheme) {
-  AppCacheManifest manifest;
-  const GURL kUrl("https://www.foo.com");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData("CACHE MANIFEST\r"
-    "CACHE: \r"
-    "relative/secureschemesameorigin\r"
-    "https://www.foo.com/secureschemesameorigin\r"
-    "http://www.xyz.com/secureschemedifforigin\r"
-    "https://www.xyz.com/secureschemedifforigin\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-
-  std::unordered_set<std::string> urls = manifest.explicit_urls;
-  const size_t kExpected = 3;
-  ASSERT_EQ(kExpected, urls.size());
-  EXPECT_TRUE(urls.find("https://www.foo.com/relative/secureschemesameorigin")
-      != urls.end());
-  EXPECT_TRUE(urls.find("https://www.foo.com/secureschemesameorigin") !=
-      urls.end());
-  EXPECT_FALSE(urls.find("http://www.xyz.com/secureschemedifforigin") !=
-      urls.end());
-  EXPECT_TRUE(urls.find("https://www.xyz.com/secureschemedifforigin") !=
-      urls.end());
-}
-
-TEST_F(AppCacheManifestParserTest, IgnoreDangerousFallbacksWithGlobalScope) {
-  const GURL kUrl("http://foo.com/scope/manifest?with_query_args");
-  const std::string kScope = kUrl.GetWithEmptyPath().path();
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "FALLBACK:\r"
-      "http://foo.com/scope/  fallback_url\r"
-      "http://foo.com/out_of_scope/ fallback_url\r");
-
-  // Scope matching depends on resolving "." as a relative url.
-  EXPECT_EQ(kUrl.GetWithoutFilename().spec(),
-            std::string("http://foo.com/scope/"));
-
-  AppCacheManifest manifest;
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-  EXPECT_EQ(2u, manifest.fallback_namespaces.size());
-
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_TRUE(manifest.did_ignore_fallback_namespaces);
-  EXPECT_EQ(1u, manifest.fallback_namespaces.size());
-  EXPECT_EQ(GURL("http://foo.com/scope/"),
-            manifest.fallback_namespaces[0].namespace_url);
-}
-
-TEST_F(AppCacheManifestParserTest, IgnoreDangerousFallbacksWithDefaultScope) {
-  const GURL kUrl("http://foo.com/scope/manifest?with_query_args");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "FALLBACK:\r"
-      "http://foo.com/scope/  fallback_url\r"
-      "http://foo.com/out_of_scope/ fallback_url\r");
-
-  // Scope matching depends on resolving "." as a relative url.
-  EXPECT_EQ(kUrl.GetWithoutFilename().spec(),
-            std::string("http://foo.com/scope/"));
-
-  AppCacheManifest manifest;
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_EQ(manifest.parser_version, 2);
-  EXPECT_FALSE(manifest.did_ignore_fallback_namespaces);
-  EXPECT_EQ(1u, manifest.fallback_namespaces.size());
-
-  manifest = AppCacheManifest();
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_PER_STANDARD, manifest));
-  EXPECT_TRUE(manifest.did_ignore_fallback_namespaces);
-  EXPECT_EQ(1u, manifest.fallback_namespaces.size());
-  EXPECT_EQ(GURL("http://foo.com/scope/"),
-            manifest.fallback_namespaces[0].namespace_url);
-}
-
-TEST_F(AppCacheManifestParserTest, InterceptUsageMetricsWithGlobalScope) {
-  const GURL url("http://foo.com/scope/manifest?with_query_args");
-  const std::string scope = url.GetWithEmptyPath().path();
-
-  struct TestCase {
-    std::string manifest;
-    int expected_none_count;
-    int expected_exact_count;
-  } test_cases[] = {
-      {"", 1, 0},
-      {"FALLBACK:\rhttp://foo.com/fallback /url\r", 1, 0},
-      {"FALLBACK:\rhttp://foo.com/fallback_pattern* /pattern isPattern\r", 1,
-       0},
-      {"NETWORK:\r*\r", 1, 0},
-      {"NETWORK:\rhttp://foo.com/network\r", 1, 0},
-      {"NETWORK:\rhttp://foo.com/network_pattern* isPattern\r", 1, 0},
-      {"CHROMIUM-INTERCEPT:\rhttp://foo.com/intercept return /url\r", 0, 1},
-      {"CHROMIUM-INTERCEPT:\r"
-       "http://foo.com/intercept* return /pattern isPattern\r",
-       0, 1},
-  };
-
-  for (const auto& test_case : test_cases) {
-    AppCacheManifest manifest;
-    base::HistogramTester tester;
-    std::string manifest_text =
-        std::string("CACHE MANIFEST\r") + test_case.manifest;
-
-    ParseManifest(url, scope, manifest_text.c_str(), manifest_text.length(),
-                  PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 0,
-                             test_case.expected_none_count);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 1,
-                             test_case.expected_exact_count);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 2, 0);
-  }
-}
-
-TEST_F(AppCacheManifestParserTest, InterceptUsageMetricsWithDefaultScope) {
-  const GURL url("http://foo.com/scope/manifest?with_query_args");
-  const std::string scope = url.GetWithoutFilename().path();
-
-  struct TestCase {
-    std::string manifest;
-    int expected_none_count;
-    int expected_exact_count;
-  } test_cases[] = {
-      {"", 1, 0},
-      {"FALLBACK:\rhttp://foo.com/fallback /url\r", 1, 0},
-      {"FALLBACK:\rhttp://foo.com/fallback_pattern* /pattern isPattern\r", 1,
-       0},
-      {"NETWORK:\r*\r", 1, 0},
-      {"NETWORK:\rhttp://foo.com/network\r", 1, 0},
-      {"NETWORK:\rhttp://foo.com/network_pattern* isPattern\r", 1, 0},
-      {"CHROMIUM-INTERCEPT:\rhttp://foo.com/intercept return /url\r", 1, 0},
-      {"CHROMIUM-INTERCEPT:\r"
-       "http://foo.com/intercept* return /pattern isPattern\r",
-       1, 0},
-      {"CHROMIUM-INTERCEPT:\r"
-       "http://foo.com/scope/intercept return /url\r",
-       0, 1},
-      {"CHROMIUM-INTERCEPT:\r"
-       "http://foo.com/scope/intercept* return /pattern isPattern\r",
-       0, 1},
-  };
-
-  for (const auto& test_case : test_cases) {
-    AppCacheManifest manifest;
-    base::HistogramTester tester;
-    std::string manifest_text =
-        std::string("CACHE MANIFEST\r") + test_case.manifest;
-
-    ParseManifest(url, scope, manifest_text.c_str(), manifest_text.length(),
-                  PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 0,
-                             test_case.expected_none_count);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 1,
-                             test_case.expected_exact_count);
-    tester.ExpectBucketCount("appcache.Manifest.InterceptUsage", 2, 0);
-  }
-}
-
-TEST_F(AppCacheManifestParserTest, OriginTrial) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://mockhost");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-
-// tools/origin_trials/generate_token.py http://mockhost AppCache
-// --expire-days=2000
-//
-// tools/origin_trials/check_token.py extracts token expiry: 1761166418.
-#define APPCACHE_ORIGIN_TRIAL_TOKEN                                            \
-  "AhiiB7vi3JiEO1/"                                                            \
-  "RQIytQslLSN3WYVu3Xd32abYhTia+91ladjnXSClfU981x+"                            \
-  "aoPimEqYVy6tWoeMZZYTpqlggAAABNeyJvcmlnaW4iOiAiaHR0cDovL21vY2tob3N0OjgwIiwg" \
-  "ImZlYXR1cmUiOiAiQXBwQ2FjaGUiLCAiZXhwaXJ5IjogMTc2MTE2NjQxOH0="
-
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "# a comment\r"
-      "CACHE:\r"
-      "NETWORK:\r"
-      "UNKNOWN:\r"
-      "ORIGIN-TRIAL:\r" APPCACHE_ORIGIN_TRIAL_TOKEN
-      " ignoredsamelinetoken\r"
-      "ignoredsecondtoken\r"
-      "ignoredthirdtoken\r"
-      "FALLBACK:\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-
-  const base::Time expect_token_expires = base::Time::FromDoubleT(1761166418);
-  EXPECT_EQ(manifest.token_expires, expect_token_expires);
-}
-
-TEST_F(AppCacheManifestParserTest, OriginTrialEmpty) {
-  AppCacheManifest manifest;
-  const GURL kUrl("http://mockhost");
-  const std::string kScope = kUrl.GetWithoutFilename().path();
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "ORIGIN-TRIAL:\r");
-
-  EXPECT_TRUE(ParseManifest(kUrl, kScope, kData.c_str(), kData.length(),
-                            PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES,
-                            manifest));
-  EXPECT_EQ(manifest.token_expires, base::Time());
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_quota_client_unittest.cc b/content/browser/appcache/appcache_quota_client_unittest.cc
deleted file mode 100644
index 9f4eb1a..0000000
--- a/content/browser/appcache/appcache_quota_client_unittest.cc
+++ /dev/null
@@ -1,436 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/memory/scoped_refptr.h"
-#include "base/run_loop.h"
-#include "base/test/bind.h"
-#include "components/services/storage/public/mojom/quota_client.mojom.h"
-#include "content/browser/appcache/appcache_quota_client.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "net/base/net_errors.h"
-#include "testing/gmock/include/gmock/gmock-matchers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/storage_key/storage_key.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom.h"
-#include "url/origin.h"
-
-namespace content {
-
-using ::blink::StorageKey;
-using ::blink::mojom::StorageType;
-
-// Declared to shorten the line lengths.
-static const StorageType kTemp = StorageType::kTemporary;
-
-// Base class for our test fixtures.
-class AppCacheQuotaClientTest : public testing::Test {
- public:
-  const StorageKey kStorageKeyA;
-  const StorageKey kStorageKeyB;
-  const StorageKey kStorageKeyOther;
-
-  AppCacheQuotaClientTest()
-      : kStorageKeyA(StorageKey::CreateFromStringForTesting("http://host")),
-        kStorageKeyB(
-            StorageKey::CreateFromStringForTesting("http://host:8000")),
-        kStorageKeyOther(
-            StorageKey::CreateFromStringForTesting("http://other")) {}
-
-  int64_t GetStorageKeyUsage(storage::mojom::QuotaClient& client,
-                             const StorageKey& storage_key,
-                             StorageType type) {
-    usage_ = -1;
-    AsyncGetStorageKeyUsage(client, storage_key, type);
-    base::RunLoop().RunUntilIdle();
-    return usage_;
-  }
-
-  const std::vector<StorageKey>& GetStorageKeysForType(
-      storage::mojom::QuotaClient& client,
-      StorageType type) {
-    storage_keys_.clear();
-    AsyncGetStorageKeysForType(client, type);
-    base::RunLoop().RunUntilIdle();
-    return storage_keys_;
-  }
-
-  const std::vector<StorageKey>& GetStorageKeysForHost(
-      storage::mojom::QuotaClient& client,
-      StorageType type,
-      const std::string& host) {
-    storage_keys_.clear();
-    AsyncGetStorageKeysForHost(client, type, host);
-    base::RunLoop().RunUntilIdle();
-    return storage_keys_;
-  }
-
-  blink::mojom::QuotaStatusCode DeleteStorageKeyData(
-      storage::mojom::QuotaClient& client,
-      StorageType type,
-      const StorageKey& storage_key) {
-    delete_status_ = blink::mojom::QuotaStatusCode::kUnknown;
-    AsyncDeleteStorageKeyData(client, type, storage_key);
-    base::RunLoop().RunUntilIdle();
-    return delete_status_;
-  }
-
-  void AsyncGetStorageKeyUsage(storage::mojom::QuotaClient& client,
-                               const StorageKey& storage_key,
-                               StorageType type) {
-    // Unretained usage is safe because this test owns a TaskEnvironment. No
-    // tasks will be executed after the test completes.
-    client.GetStorageKeyUsage(
-        storage_key, type,
-        base::BindOnce(&AppCacheQuotaClientTest::OnGetStorageKeyUsageComplete,
-                       base::Unretained(this)));
-  }
-
-  void AsyncGetStorageKeysForType(storage::mojom::QuotaClient& client,
-                                  StorageType type) {
-    // Unretained usage is safe because this test owns a TaskEnvironment. No
-    // tasks will be executed after the test completes.
-    client.GetStorageKeysForType(
-        type, base::BindOnce(&AppCacheQuotaClientTest::OnGetStorageKeysComplete,
-                             base::Unretained(this)));
-  }
-
-  void AsyncGetStorageKeysForHost(storage::mojom::QuotaClient& client,
-                                  StorageType type,
-                                  const std::string& host) {
-    // Unretained usage is safe because this test owns a TaskEnvironment. No
-    // tasks will be executed after the test completes.
-    client.GetStorageKeysForHost(
-        type, host,
-        base::BindOnce(&AppCacheQuotaClientTest::OnGetStorageKeysComplete,
-                       base::Unretained(this)));
-  }
-
-  void AsyncDeleteStorageKeyData(storage::mojom::QuotaClient& client,
-                                 StorageType type,
-                                 const StorageKey& storage_key) {
-    // Unretained usage is safe because this test owns a TaskEnvironment. No
-    // tasks will be executed after the test completes.
-    client.DeleteStorageKeyData(
-        storage_key, type,
-        base::BindOnce(&AppCacheQuotaClientTest::OnDeleteStorageKeyDataComplete,
-                       base::Unretained(this)));
-  }
-
-  void SetUsageMapEntry(const StorageKey& storage_key, int64_t usage) {
-    mock_service_.storage()->usage_map_[storage_key.origin()] = usage;
-  }
-
-  std::unique_ptr<AppCacheQuotaClient> CreateClient() {
-    return std::make_unique<AppCacheQuotaClient>(mock_service_.AsWeakPtr());
-  }
-
-  void Call_NotifyStorageReady(AppCacheQuotaClient& client) {
-    client.NotifyStorageReady();
-  }
-
-  void Call_NotifyServiceDestroyed(AppCacheQuotaClient& client) {
-    client.NotifyServiceDestroyed();
-  }
-
-  void Call_OnMojoDisconnect(AppCacheQuotaClient& client) {
-    client.OnMojoDisconnect();
-  }
-
- protected:
-  void OnGetStorageKeyUsageComplete(int64_t usage) {
-    ++num_get_storage_key_usage_completions_;
-    usage_ = usage;
-  }
-
-  void OnGetStorageKeysComplete(const std::vector<StorageKey>& storage_keys) {
-    ++num_get_storage_keys_completions_;
-    storage_keys_ = storage_keys;
-  }
-
-  void OnDeleteStorageKeyDataComplete(blink::mojom::QuotaStatusCode status) {
-    ++num_delete_storage_keys_completions_;
-    delete_status_ = status;
-  }
-
-  BrowserTaskEnvironment task_environment_;
-  int64_t usage_ = 0;
-  std::vector<StorageKey> storage_keys_;
-  blink::mojom::QuotaStatusCode delete_status_ =
-      blink::mojom::QuotaStatusCode::kUnknown;
-  int num_get_storage_key_usage_completions_ = 0;
-  int num_get_storage_keys_completions_ = 0;
-  int num_delete_storage_keys_completions_ = 0;
-  MockAppCacheService mock_service_;
-};
-
-TEST_F(AppCacheQuotaClientTest, BasicCreateDestroy) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-  Call_OnMojoDisconnect(*client);
-  Call_NotifyServiceDestroyed(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, QuotaManagerDestroyedInCallback) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-  client->DeleteStorageKeyData(
-      kStorageKeyA, kTemp,
-      base::BindLambdaForTesting([&](blink::mojom::QuotaStatusCode) {
-        Call_OnMojoDisconnect(*client);
-      }));
-  Call_NotifyServiceDestroyed(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, EmptyService) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  EXPECT_EQ(0, GetStorageKeyUsage(*client, kStorageKeyA, kTemp));
-  EXPECT_TRUE(GetStorageKeysForType(*client, kTemp).empty());
-  EXPECT_TRUE(
-      GetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host())
-          .empty());
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
-            DeleteStorageKeyData(*client, kTemp, kStorageKeyA));
-
-  Call_NotifyServiceDestroyed(*client);
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, NoService) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-  Call_NotifyServiceDestroyed(*client);
-
-  EXPECT_EQ(0, GetStorageKeyUsage(*client, kStorageKeyA, kTemp));
-  EXPECT_TRUE(GetStorageKeysForType(*client, kTemp).empty());
-  EXPECT_TRUE(
-      GetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host())
-          .empty());
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kErrorAbort,
-            DeleteStorageKeyData(*client, kTemp, kStorageKeyA));
-
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, GetStorageKeyUsage) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  EXPECT_EQ(1000, GetStorageKeyUsage(*client, kStorageKeyA, kTemp));
-  EXPECT_EQ(0, GetStorageKeyUsage(*client, kStorageKeyB, kTemp));
-
-  Call_NotifyServiceDestroyed(*client);
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, GetStorageKeysForHost) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  EXPECT_EQ(kStorageKeyA.origin().host(), kStorageKeyB.origin().host());
-  EXPECT_NE(kStorageKeyA.origin().host(), kStorageKeyOther.origin().host());
-
-  std::vector<StorageKey> storage_keys =
-      GetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host());
-  EXPECT_TRUE(storage_keys.empty());
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  SetUsageMapEntry(kStorageKeyB, 10);
-  SetUsageMapEntry(kStorageKeyOther, 500);
-
-  storage_keys =
-      GetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host());
-  EXPECT_EQ(2ul, storage_keys.size());
-  EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA));
-  EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyB));
-
-  storage_keys =
-      GetStorageKeysForHost(*client, kTemp, kStorageKeyOther.origin().host());
-  EXPECT_EQ(1ul, storage_keys.size());
-  EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyOther));
-
-  Call_NotifyServiceDestroyed(*client);
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, GetStorageKeysForType) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  EXPECT_TRUE(GetStorageKeysForType(*client, kTemp).empty());
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  SetUsageMapEntry(kStorageKeyB, 10);
-
-  std::vector<StorageKey> storage_keys = GetStorageKeysForType(*client, kTemp);
-  EXPECT_EQ(2ul, storage_keys.size());
-  EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyA));
-  EXPECT_THAT(storage_keys, testing::Contains(kStorageKeyB));
-
-  Call_NotifyServiceDestroyed(*client);
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, DeleteStorageKeyData) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kOk,
-            DeleteStorageKeyData(*client, kTemp, kStorageKeyA));
-  EXPECT_EQ(1, mock_service_.delete_called_count());
-
-  mock_service_.set_mock_delete_appcaches_for_origin_result(
-      net::ERR_ABORTED);
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kErrorAbort,
-            DeleteStorageKeyData(*client, kTemp, kStorageKeyA));
-  EXPECT_EQ(2, mock_service_.delete_called_count());
-
-  Call_OnMojoDisconnect(*client);
-  Call_NotifyServiceDestroyed(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, PendingRequests) {
-  auto client = CreateClient();
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  SetUsageMapEntry(kStorageKeyB, 10);
-  SetUsageMapEntry(kStorageKeyOther, 500);
-
-  // Queue up some requests.
-  AsyncGetStorageKeyUsage(*client, kStorageKeyA, kTemp);
-  AsyncGetStorageKeyUsage(*client, kStorageKeyB, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host());
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyOther.origin().host());
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyA);
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyB);
-
-  EXPECT_EQ(0, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(0, num_get_storage_keys_completions_);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(0, num_get_storage_keys_completions_);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-
-  // Pending requests should get serviced when the appcache is ready.
-  Call_NotifyStorageReady(*client);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(2, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(4, num_get_storage_keys_completions_);
-  EXPECT_EQ(2, num_delete_storage_keys_completions_);
-
-  // They should be serviced in order requested.
-  EXPECT_EQ(10, usage_);
-  EXPECT_EQ(1ul, storage_keys_.size());
-  EXPECT_THAT(storage_keys_, testing::Contains(kStorageKeyOther));
-
-  Call_NotifyServiceDestroyed(*client);
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, DestroyServiceWithPending) {
-  auto client = CreateClient();
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  SetUsageMapEntry(kStorageKeyB, 10);
-  SetUsageMapEntry(kStorageKeyOther, 500);
-
-  // Queue up some requests prior to being ready.
-  AsyncGetStorageKeyUsage(*client, kStorageKeyA, kTemp);
-  AsyncGetStorageKeyUsage(*client, kStorageKeyB, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host());
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyOther.origin().host());
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyA);
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyB);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(0, num_get_storage_keys_completions_);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-
-  // Kill the service.
-  Call_NotifyServiceDestroyed(*client);
-
-  // All should have been aborted and called completion.
-  EXPECT_EQ(2, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(4, num_get_storage_keys_completions_);
-  EXPECT_EQ(2, num_delete_storage_keys_completions_);
-  EXPECT_EQ(0, usage_);
-  EXPECT_TRUE(storage_keys_.empty());
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kErrorAbort, delete_status_);
-
-  Call_OnMojoDisconnect(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, DestroyQuotaManagerWithPending) {
-  auto client = CreateClient();
-
-  SetUsageMapEntry(kStorageKeyA, 1000);
-  SetUsageMapEntry(kStorageKeyB, 10);
-  SetUsageMapEntry(kStorageKeyOther, 500);
-
-  // Queue up some requests prior to being ready.
-  AsyncGetStorageKeyUsage(*client, kStorageKeyA, kTemp);
-  AsyncGetStorageKeyUsage(*client, kStorageKeyB, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForType(*client, kTemp);
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyA.origin().host());
-  AsyncGetStorageKeysForHost(*client, kTemp, kStorageKeyOther.origin().host());
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyA);
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyB);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(0, num_get_storage_keys_completions_);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-
-  // Kill the quota manager.
-  Call_OnMojoDisconnect(*client);
-  Call_NotifyStorageReady(*client);
-
-  // Callbacks should be deleted and not called.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, num_get_storage_key_usage_completions_);
-  EXPECT_EQ(0, num_get_storage_keys_completions_);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-
-  Call_NotifyServiceDestroyed(*client);
-}
-
-TEST_F(AppCacheQuotaClientTest, DestroyWithDeleteInProgress) {
-  auto client = CreateClient();
-  Call_NotifyStorageReady(*client);
-
-  // Start an async delete.
-  AsyncDeleteStorageKeyData(*client, kTemp, kStorageKeyB);
-  EXPECT_EQ(0, num_delete_storage_keys_completions_);
-
-  // Kill the service.
-  Call_NotifyServiceDestroyed(*client);
-
-  // Should have been aborted.
-  EXPECT_EQ(1, num_delete_storage_keys_completions_);
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kErrorAbort, delete_status_);
-
-  // A real completion callback from the service should
-  // be dropped if it comes in after NotifyServiceDestroyed.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, num_delete_storage_keys_completions_);
-  EXPECT_EQ(blink::mojom::QuotaStatusCode::kErrorAbort, delete_status_);
-
-  Call_OnMojoDisconnect(*client);
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_request_handler_unittest.cc b/content/browser/appcache/appcache_request_handler_unittest.cc
deleted file mode 100644
index 307bc26..0000000
--- a/content/browser/appcache/appcache_request_handler_unittest.cc
+++ /dev/null
@@ -1,800 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_request_handler.h"
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/containers/stack.h"
-#include "base/cxx17_backports.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_backend_impl.h"
-#include "content/browser/appcache/appcache_request.h"
-#include "content/browser/appcache/appcache_url_loader.h"
-#include "content/browser/appcache/mock_appcache_policy.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "services/network/public/cpp/resource_request.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-
-namespace content {
-
-static const int kMockProcessId = 1;
-
-// TODO(michaeln/ananta)
-// Build on the abstractions provided by the request and the job classes to
-// provide mock request and job classes to the AppCacheRequestHandler class
-// which would make it testable. It would also allow us to avoid the URLRequest
-// and URLLoader semantics in the test cases here,
-class AppCacheRequestHandlerTest : public ::testing::Test {
- public:
-  // Helper callback to run a test on our io_thread. The io_thread is spun up
-  // once and reused for all tests.
-  template <class Method>
-  void MethodWrapper(Method method) {
-    SetUpTest();
-    (this->*method)();
-  }
-
-  // Test harness --------------------------------------------------
-
-  AppCacheRequestHandlerTest() : host_(nullptr), request_(nullptr) {
-    feature_list_.InitAndEnableFeature(kAppCacheAlwaysFallbackToNetwork);
-    AppCacheRequestHandler::SetRunningInTests(true);
-  }
-
-  ~AppCacheRequestHandlerTest() override {
-    AppCacheRequestHandler::SetRunningInTests(false);
-  }
-
-  template <class Method>
-  void RunTestOnUIThread(Method method) {
-    base::RunLoop run_loop;
-    test_finished_cb_ = run_loop.QuitClosure();
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheRequestHandlerTest::MethodWrapper<Method>,
-                       base::Unretained(this), method));
-    run_loop.Run();
-  }
-
-  void SetUpTest() {
-    mock_service_ = std::make_unique<MockAppCacheService>();
-    mock_policy_ = std::make_unique<MockAppCachePolicy>();
-    mock_service_->set_appcache_policy(mock_policy_.get());
-    const auto kHostId = base::UnguessableToken::Create();
-    const int kRenderFrameId = 2;
-    mojo::PendingRemote<blink::mojom::AppCacheFrontend> frontend_remote;
-    ignore_result(frontend_remote.InitWithNewPipeAndPassReceiver());
-    mock_service_->RegisterHost(
-        host_remote_.BindNewPipeAndPassReceiver(), std::move(frontend_remote),
-        kHostId, kRenderFrameId, kMockProcessId,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            kMockProcessId),
-        GetBadMessageCallback());
-    host_ = mock_service_->GetHost(kHostId);
-  }
-
-  void TearDownTest() {
-    if (appcache_url_loader_)
-      appcache_url_loader_->DeleteIfNeeded();
-    appcache_url_loader_.reset();
-    handler_.reset();
-    request_ = nullptr;
-    mock_service_.reset();
-    mock_policy_.reset();
-    host_remote_.reset();
-    host_ = nullptr;
-  }
-
-  void TestFinished() {
-    // We unwind the stack prior to finishing up to let stack
-    // based objects get deleted.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheRequestHandlerTest::TestFinishedUnwound,
-                       base::Unretained(this)));
-  }
-
-  void TestFinishedUnwound() {
-    TearDownTest();
-    std::move(test_finished_cb_).Run();
-  }
-
-  void PushNextTask(base::OnceClosure task) {
-    task_stack_.push(std::move(task));
-  }
-
-  void ScheduleNextTask() {
-    if (task_stack_.empty()) {
-      TestFinished();
-      return;
-    }
-    base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
-                                                  std::move(task_stack_.top()));
-    task_stack_.pop();
-  }
-
-  void SetAppCacheURLLoader(AppCacheURLLoader* loader) {
-    if (appcache_url_loader_) {
-      appcache_url_loader_->DeleteIfNeeded();
-      appcache_url_loader_ = nullptr;
-    }
-    if (!loader)
-      return;
-    appcache_url_loader_ = loader->GetWeakPtr();
-  }
-
-  AppCacheURLLoader* loader() { return appcache_url_loader_.get(); }
-
-  // MainResource_Miss --------------------------------------------------
-
-  void MainResource_Miss() {
-    PushNextTask(
-        base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Miss,
-                       base::Unretained(this)));
-
-    CreateRequestAndHandler(GURL("http://blah"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    // We have to wait for completion of storage->FindResponseForMainRequest.
-    ScheduleNextTask();
-  }
-
-  void Verify_MainResource_Miss() {
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_TRUE(loader()->IsDeliveringNetworkResponse());
-
-    int64_t cache_id = blink::mojom::kAppCacheNoCacheId;
-    GURL manifest_url;
-    handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, cache_id);
-    EXPECT_EQ(GURL(), manifest_url);
-    EXPECT_EQ(0, handler_->found_group_id_);
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
-
-    TestFinished();
-  }
-
-  // MainResource_Hit --------------------------------------------------
-
-  void MainResource_Hit() {
-    PushNextTask(
-        base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Hit,
-                       base::Unretained(this)));
-
-    CreateRequestAndHandler(GURL("http://blah"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    mock_storage()->SimulateFindMainResource(
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), GURL(), AppCacheEntry(), 1,
-        2, GURL("http://blah/manifest/"));
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    // We have to wait for completion of storage->FindResponseForMainRequest.
-    ScheduleNextTask();
-  }
-
-  void Verify_MainResource_Hit() {
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_TRUE(loader()->IsDeliveringAppCacheResponse());
-
-    int64_t cache_id = blink::mojom::kAppCacheNoCacheId;
-    GURL manifest_url;
-    handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
-    EXPECT_EQ(1, cache_id);
-    EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
-    EXPECT_EQ(2, handler_->found_group_id_);
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    EXPECT_EQ(GURL("http://blah/manifest/"), host_->preferred_manifest_url());
-
-    TestFinished();
-  }
-
-  // MainResource_Fallback --------------------------------------------------
-
-  void MainResource_Fallback() {
-    PushNextTask(base::BindOnce(
-        &AppCacheRequestHandlerTest::Verify_MainResource_Fallback,
-        base::Unretained(this)));
-
-    CreateRequestAndHandler(GURL("http://blah"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    mock_storage()->SimulateFindMainResource(
-        AppCacheEntry(), GURL("http://blah/fallbackurl"),
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), 1, 2,
-        GURL("http://blah/manifest/"));
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    // We have to wait for completion of storage->FindResponseForMainRequest.
-    ScheduleNextTask();
-  }
-
-  void SimulateResponseCode(int response_code) {
-    net::HttpResponseInfo info;
-    std::string headers =
-        base::StringPrintf("HTTP/1.1 %i Muffin\r\n\r\n", response_code);
-    info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        net::HttpUtil::AssembleRawHeaders(headers));
-
-    auto response = network::mojom::URLResponseHead::New();
-    response->headers = info.headers;
-    request_->set_response(std::move(response));
-    DCHECK_EQ(response_code, request_->GetResponseCode());
-  }
-
-  void SimulateResponseInfo(const net::HttpResponseInfo& info) {
-    auto response = network::mojom::URLResponseHead::New();
-    response->headers = info.headers;
-    request_->set_response(std::move(response));
-  }
-
-  void Verify_MainResource_Fallback() {
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_TRUE(loader()->IsDeliveringNetworkResponse());
-
-    // Simulate an http error of the real network job.
-    SimulateResponseCode(500);
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsDeliveringAppCacheResponse());
-
-    int64_t cache_id = blink::mojom::kAppCacheNoCacheId;
-    GURL manifest_url;
-    handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
-    EXPECT_EQ(1, cache_id);
-    EXPECT_EQ(GURL("http://blah/manifest/"), manifest_url);
-    EXPECT_TRUE(host_->main_resource_was_namespace_entry_);
-    EXPECT_EQ(GURL("http://blah/fallbackurl"), host_->namespace_entry_url_);
-
-    EXPECT_EQ(GURL("http://blah/manifest/"), host_->preferred_manifest_url());
-
-    TestFinished();
-  }
-
-  // MainResource_FallbackOverride --------------------------------------------
-
-  void MainResource_FallbackOverride() {
-    PushNextTask(base::BindOnce(
-        &AppCacheRequestHandlerTest::Verify_MainResource_FallbackOverride,
-        base::Unretained(this)));
-
-    CreateRequestAndHandler(GURL("http://blah/fallback-override"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    mock_storage()->SimulateFindMainResource(
-        AppCacheEntry(), GURL("http://blah/fallbackurl"),
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), 1, 2,
-        GURL("http://blah/manifest/"));
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    // We have to wait for completion of storage->FindResponseForMainRequest.
-    ScheduleNextTask();
-  }
-
-  void Verify_MainResource_FallbackOverride() {
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_TRUE(loader()->IsDeliveringNetworkResponse());
-
-    // Simulate an http error of the real network job, but with custom
-    // headers that override the fallback behavior.
-    const char kOverrideHeaders[] =
-        "HTTP/1.1 404 BOO HOO\0"
-        "x-chromium-appcache-fallback-override: disallow-fallback\0"
-        "\0";
-    net::HttpResponseInfo info;
-    info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(kOverrideHeaders, base::size(kOverrideHeaders)));
-    SimulateResponseInfo(info);
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    // GetExtraResponseInfo should return no information.
-    int64_t cache_id = blink::mojom::kAppCacheNoCacheId;
-    GURL manifest_url;
-    handler_->GetExtraResponseInfo(&cache_id, &manifest_url);
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, cache_id);
-    EXPECT_TRUE(manifest_url.is_empty());
-
-    TestFinished();
-  }
-
-  // SubResource_Miss_WithNoCacheSelected ----------------------------------
-
-  void SubResource_Miss_WithNoCacheSelected() {
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    // We avoid creating handler when possible, sub-resource requests are not
-    // subject to retrieval from an appcache when there's no associated cache.
-    EXPECT_FALSE(handler_.get());
-
-    TestFinished();
-  }
-
-  // SubResource_Miss_WithCacheSelected ----------------------------------
-
-  void SubResource_Miss_WithCacheSelected() {
-    // A sub-resource load where the resource is not in an appcache, or
-    // in a network or fallback namespace, should result in a fallback to the
-    // network rather than an error, as we treat all network namespaces as
-    // including '*'.
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(loader());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // SubResource_Miss_WithWaitForCacheSelection -----------------------------
-
-  void SubResource_Miss_WithWaitForCacheSelection() {
-    // Precondition, the host is waiting on cache selection.
-    scoped_refptr<AppCache> cache(MakeNewCache());
-    host_->pending_selected_cache_id_ = cache->cache_id();
-    host_->set_preferred_manifest_url(cache->owning_group()->manifest_url());
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    host_->FinishCacheSelection(cache.get(), nullptr, base::DoNothing());
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_TRUE(loader()->IsDeliveringNetworkResponse());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // SubResource_Hit -----------------------------
-
-  void SubResource_Hit() {
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsDeliveringAppCacheResponse());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // SubResource_RedirectFallback -----------------------------
-
-  void SubResource_RedirectFallback() {
-    // Redirects to resources in the a different origin are subject to
-    // fallback namespaces.
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(
-        AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(loader());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://not_blah/redirect")));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsDeliveringAppCacheResponse());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // SubResource_NoRedirectFallback -----------------------------
-
-  void SubResource_NoRedirectFallback() {
-    // Redirects to resources in the same-origin are not subject to
-    // fallback namespaces.
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(
-        AppCacheEntry(), AppCacheEntry(AppCacheEntry::EXPLICIT, 1), false);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(loader());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-
-    SimulateResponseCode(200);
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // SubResource_Network -----------------------------
-
-  void SubResource_Network() {
-    // A sub-resource load where the resource is in a network namespace,
-    // should result in the system using a 'real' job to do the network
-    // retrieval.
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(AppCacheEntry(), AppCacheEntry(),
-                                            true);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(loader());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(loader());
-    SetAppCacheURLLoader(handler_->MaybeLoadFallbackForResponse(nullptr));
-    EXPECT_FALSE(loader());
-
-    TestFinished();
-  }
-
-  // DestroyedHost -----------------------------
-
-  void DestroyedHost() {
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-
-    mock_service_->EraseHost(host_->host_id());
-    host_ = nullptr;
-
-    EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
-    TestFinished();
-  }
-
-  // DestroyedHostWithWaitingJob -----------------------------
-
-  void DestroyedHostWithWaitingJob() {
-    // Precondition, the host is waiting on cache selection.
-    host_->pending_selected_cache_id_ = 1;
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    mock_service_->EraseHost(host_->host_id());
-    host_ = nullptr;
-
-    EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
-    TestFinished();
-  }
-
-  // DestroyedService -----------------------------
-
-  void DestroyedService() {
-    host_->AssociateCompleteCache(MakeNewCache());
-
-    mock_storage()->SimulateFindSubResource(
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), AppCacheEntry(), false);
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-
-    mock_service_.reset();
-    mock_policy_.reset();
-    host_ = nullptr;
-
-    EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("http://blah/redirect")));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
-    TestFinished();
-  }
-
-  // UnsupportedScheme -----------------------------
-
-  void UnsupportedScheme() {
-    // Precondition, the host is waiting on cache selection.
-    host_->pending_selected_cache_id_ = 1;
-
-    CreateRequestAndHandler(GURL("ftp://blah/"), host_,
-                            network::mojom::RequestDestination::kEmpty);
-    EXPECT_TRUE(handler_.get());  // we could redirect to http (conceivably)
-
-    EXPECT_FALSE(handler_->MaybeLoadResource(nullptr));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForRedirect(
-        nullptr, GURL("ftp://blah/redirect")));
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
-    TestFinished();
-  }
-
-  // CanceledRequest -----------------------------
-
-  void CanceledRequest() {
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-    EXPECT_FALSE(loader()->IsStarted());
-
-    base::WeakPtr<AppCacheURLLoader> weak_job = loader()->GetWeakPtr();
-
-    EXPECT_FALSE(handler_->MaybeLoadFallbackForResponse(nullptr));
-
-    TestFinished();
-  }
-
-  // MainResource_Blocked --------------------------------------------------
-
-  void MainResource_Blocked() {
-    PushNextTask(
-        base::BindOnce(&AppCacheRequestHandlerTest::Verify_MainResource_Blocked,
-                       base::Unretained(this)));
-
-    CreateRequestAndHandler(GURL("http://blah/"), host_,
-                            network::mojom::RequestDestination::kDocument);
-    EXPECT_TRUE(handler_.get());
-
-    mock_policy_->can_load_return_value_ = false;
-    mock_storage()->SimulateFindMainResource(
-        AppCacheEntry(AppCacheEntry::EXPLICIT, 1), GURL(), AppCacheEntry(), 1,
-        2, GURL("http://blah/manifest/"));
-
-    SetAppCacheURLLoader(handler_->MaybeLoadResource(nullptr));
-    EXPECT_TRUE(loader());
-    EXPECT_TRUE(loader()->IsWaiting());
-
-    // We have to wait for completion of storage->FindResponseForMainRequest.
-    ScheduleNextTask();
-  }
-
-  void Verify_MainResource_Blocked() {
-    EXPECT_FALSE(loader()->IsWaiting());
-    EXPECT_FALSE(loader()->IsDeliveringAppCacheResponse());
-
-    EXPECT_EQ(0, handler_->found_cache_id_);
-    EXPECT_EQ(0, handler_->found_group_id_);
-    EXPECT_TRUE(handler_->found_manifest_url_.is_empty());
-    EXPECT_TRUE(host_->preferred_manifest_url().is_empty());
-    EXPECT_TRUE(host_->main_resource_blocked_);
-    EXPECT_EQ(host_->blocked_manifest_url_, "http://blah/manifest/");
-
-    TestFinished();
-  }
-
-  // Test case helpers --------------------------------------------------
-
-  AppCache* MakeNewCache() {
-    AppCache* cache =
-        new AppCache(mock_storage(), mock_storage()->NewCacheId());
-    cache->set_complete(true);
-    AppCacheGroup* group =
-        new AppCacheGroup(mock_storage(), GURL("http://blah/manifest"),
-                          mock_storage()->NewGroupId());
-    group->AddCache(cache);
-    return cache;
-  }
-
-  mojo::ReportBadMessageCallback GetBadMessageCallback() {
-    return base::BindOnce(&AppCacheRequestHandlerTest::OnBadMessage,
-                          base::Unretained(this));
-  }
-
-  void OnBadMessage(const std::string& reason) { NOTREACHED(); }
-
-  MockAppCacheStorage* mock_storage() {
-    return static_cast<MockAppCacheStorage*>(mock_service_->storage());
-  }
-
-  void CreateRequestAndHandler(const GURL& url,
-                               AppCacheHost* host,
-                               network::mojom::RequestDestination destination) {
-    network::ResourceRequest resource_request;
-    resource_request.url = url;
-    resource_request.method = "GET";
-    auto request = std::make_unique<AppCacheRequest>(resource_request);
-    request_ = request.get();
-    handler_ =
-        host->CreateRequestHandler(std::move(request), destination, false,
-                                   FrameTreeNode::kFrameTreeNodeInvalidId);
-  }
-
-  // Data members --------------------------------------------------
-  base::test::ScopedFeatureList feature_list_;
-  BrowserTaskEnvironment task_environment_;
-
-  base::OnceClosure test_finished_cb_;
-  base::stack<base::OnceClosure> task_stack_;
-  std::unique_ptr<MockAppCacheService> mock_service_;
-  std::unique_ptr<MockAppCachePolicy> mock_policy_;
-  AppCacheHost* host_;
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote_;
-  AppCacheRequest* request_;
-  std::unique_ptr<AppCacheRequestHandler> handler_;
-  base::WeakPtr<AppCacheURLLoader> appcache_url_loader_;
-};
-
-TEST_F(AppCacheRequestHandlerTest, MainResource_Miss) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::MainResource_Miss);
-}
-
-TEST_F(AppCacheRequestHandlerTest, MainResource_Hit) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::MainResource_Hit);
-}
-
-TEST_F(AppCacheRequestHandlerTest, MainResource_Fallback) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::MainResource_Fallback);
-}
-
-TEST_F(AppCacheRequestHandlerTest, MainResource_FallbackOverride) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::MainResource_FallbackOverride);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithNoCacheSelected) {
-  RunTestOnUIThread(
-      &AppCacheRequestHandlerTest::SubResource_Miss_WithNoCacheSelected);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithCacheSelected) {
-  RunTestOnUIThread(
-      &AppCacheRequestHandlerTest::SubResource_Miss_WithCacheSelected);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_Miss_WithWaitForCacheSelection) {
-  RunTestOnUIThread(
-      &AppCacheRequestHandlerTest::SubResource_Miss_WithWaitForCacheSelection);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_Hit) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::SubResource_Hit);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_RedirectFallback) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::SubResource_RedirectFallback);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_NoRedirectFallback) {
-  RunTestOnUIThread(
-      &AppCacheRequestHandlerTest::SubResource_NoRedirectFallback);
-}
-
-TEST_F(AppCacheRequestHandlerTest, SubResource_Network) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::SubResource_Network);
-}
-
-TEST_F(AppCacheRequestHandlerTest, DestroyedHost) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::DestroyedHost);
-}
-
-TEST_F(AppCacheRequestHandlerTest, DestroyedHostWithWaitingJob) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::DestroyedHostWithWaitingJob);
-}
-
-TEST_F(AppCacheRequestHandlerTest, DestroyedService) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::DestroyedService);
-}
-
-TEST_F(AppCacheRequestHandlerTest, UnsupportedScheme) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::UnsupportedScheme);
-}
-
-TEST_F(AppCacheRequestHandlerTest, CanceledRequest) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::CanceledRequest);
-}
-
-TEST_F(AppCacheRequestHandlerTest, MainResource_Blocked) {
-  RunTestOnUIThread(&AppCacheRequestHandlerTest::MainResource_Blocked);
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_response_unittest.cc b/content/browser/appcache/appcache_response_unittest.cc
deleted file mode 100644
index 0fdf25f4..0000000
--- a/content/browser/appcache/appcache_response_unittest.cc
+++ /dev/null
@@ -1,822 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-#include <string.h>
-
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/containers/stack.h"
-#include "base/cxx17_backports.h"
-#include "base/location.h"
-#include "base/message_loop/message_pump_type.h"
-#include "base/pickle.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/escape.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/bind.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/timer/timer.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "net/base/io_buffer.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using net::IOBuffer;
-using net::WrappedIOBuffer;
-
-namespace content {
-
-namespace {
-
-constexpr int kNumBlocks = 4;
-constexpr int kBlockSize = 1024;
-constexpr int kNoSuchResponseId = 123;
-
-}  // namespace
-
-class AppCacheResponseTest : public testing::Test {
- public:
-  // Test Harness -------------------------------------------------------------
-
-  // Helper class used to verify test results
-  class MockStorageDelegate : public AppCacheStorage::Delegate {
-   public:
-    explicit MockStorageDelegate(
-        AppCacheResponseTest* test,
-        base::OnceClosure response_info_loaded_callback)
-        : loaded_info_id_(0),
-          test_(test),
-          response_info_loaded_callback_(
-              std::move(response_info_loaded_callback)) {}
-
-    void OnResponseInfoLoaded(AppCacheResponseInfo* info,
-                              int64_t response_id) override {
-      loaded_info_ = info;
-      loaded_info_id_ = response_id;
-      std::move(response_info_loaded_callback_).Run();
-    }
-
-    scoped_refptr<AppCacheResponseInfo> loaded_info_;
-    int64_t loaded_info_id_;
-    AppCacheResponseTest* test_;
-    base::OnceClosure response_info_loaded_callback_;
-  };
-
-  enum class CallbackMode {
-    kPostTask,
-    kImmediate,
-  };
-
-  AppCacheResponseTest() = default;
-  ~AppCacheResponseTest() override = default;
-
-  template <class Method>
-  void RunTestOnIOThread(Method method) {
-    (this->*method)();
-  }
-
-  void SetUp() override {
-    task_environment_ = std::make_unique<content::BrowserTaskEnvironment>();
-    service_ = std::make_unique<MockAppCacheService>();
-  }
-
-  // Wrappers to call AppCacheResponseReader/Writer Read and Write methods
-
-  void WriteBasicResponse(base::OnceClosure callback) {
-    static const char kHttpHeaders[] =
-        "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
-    static const char kHttpBody[] = "Hello";
-    scoped_refptr<IOBuffer> body =
-        base::MakeRefCounted<WrappedIOBuffer>(kHttpBody);
-    std::string raw_headers(kHttpHeaders, base::size(kHttpHeaders));
-    WriteResponse(MakeHttpResponseInfo(raw_headers), body.get(),
-                  strlen(kHttpBody), std::move(callback));
-  }
-
-  int basic_response_size() { return 5; }  // should match kHttpBody above
-
-  void WriteResponse(std::unique_ptr<net::HttpResponseInfo> head,
-                     IOBuffer* body,
-                     int body_len,
-                     base::OnceClosure callback) {
-    DCHECK(body);
-    scoped_refptr<IOBuffer> body_ref(body);
-    WriteResponseHead(
-        std::move(head),
-        base::BindOnce(&AppCacheResponseTest::WriteResponseBody,
-                       base::Unretained(this), body_ref, body_len,
-                       CallbackMode::kPostTask, std::move(callback)));
-  }
-
-  void WriteResponseHead(std::unique_ptr<net::HttpResponseInfo> head,
-                         base::OnceClosure callback) {
-    EXPECT_FALSE(writer_->IsWritePending());
-    expected_write_result_ = GetHttpResponseInfoSize(*head);
-    write_info_buffer_ =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(std::move(head));
-    writer_->WriteInfo(
-        write_info_buffer_.get(),
-        base::BindOnce(&AppCacheResponseTest::OnWriteInfoComplete,
-                       base::Unretained(this), std::move(callback)));
-  }
-
-  void WriteResponseBody(scoped_refptr<IOBuffer> io_buffer,
-                         int buf_len,
-                         CallbackMode callback_mode,
-                         base::OnceClosure callback) {
-    EXPECT_FALSE(writer_->IsWritePending());
-    write_buffer_ = std::move(io_buffer);
-    expected_write_result_ = buf_len;
-    writer_->WriteData(write_buffer_.get(), buf_len,
-                       base::BindOnce(&AppCacheResponseTest::OnWriteComplete,
-                                      base::Unretained(this), callback_mode,
-                                      std::move(callback)));
-  }
-
-  void WriteResponseMetadata(scoped_refptr<IOBuffer> io_buffer,
-                             int buf_len,
-                             base::OnceClosure callback) {
-    EXPECT_FALSE(metadata_writer_->IsWritePending());
-    write_buffer_ = io_buffer;
-    expected_write_result_ = buf_len;
-    metadata_writer_->WriteMetadata(
-        write_buffer_.get(), buf_len,
-        base::BindOnce(&AppCacheResponseTest::OnMetadataWriteComplete,
-                       base::Unretained(this), std::move(callback)));
-  }
-
-  void ReadResponseBody(scoped_refptr<IOBuffer> io_buffer,
-                        int buf_len,
-                        CallbackMode callback_mode,
-                        base::OnceClosure callback) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_buffer_ = io_buffer;
-    expected_read_result_ = buf_len;
-    reader_->ReadData(read_buffer_.get(), buf_len,
-                      base::BindOnce(&AppCacheResponseTest::OnReadComplete,
-                                     base::Unretained(this), callback_mode,
-                                     std::move(callback)));
-  }
-
-  void WriteOneBlock(int block_number,
-                     CallbackMode callback_mode,
-                     base::OnceClosure callback) {
-    scoped_refptr<IOBuffer> io_buffer =
-        base::MakeRefCounted<IOBuffer>(kBlockSize);
-    FillData(block_number, io_buffer->data(), kBlockSize);
-    WriteResponseBody(io_buffer, kBlockSize, callback_mode,
-                      std::move(callback));
-  }
-
-  void WriteOutBlocks(base::OnceClosure callback) {
-    writer_ = service_->storage()->CreateResponseWriter(GURL());
-    written_response_id_ = writer_->response_id();
-
-    for (int i = 0; i < kNumBlocks; ++i) {
-      callback = base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
-                                base::Unretained(this), kNumBlocks - i,
-                                CallbackMode::kPostTask, std::move(callback));
-    }
-    std::move(callback).Run();
-  }
-
-  void ReadInBlocks(base::OnceClosure callback) {
-    writer_.reset();
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    for (int i = 0; i < kNumBlocks; ++i) {
-      callback = base::BindOnce(&AppCacheResponseTest::ReadOneBlock,
-                                base::Unretained(this), kNumBlocks - i,
-                                std::move(callback));
-    }
-    std::move(callback).Run();
-  }
-
-  void ReadOneBlock(int block_number, base::OnceClosure read_verify_callback) {
-    ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize,
-                     CallbackMode::kPostTask,
-                     base::BindOnce(&AppCacheResponseTest::VerifyOneBlock,
-                                    base::Unretained(this), block_number,
-                                    std::move(read_verify_callback)));
-  }
-
-  void VerifyOneBlock(int block_number,
-                      base::OnceClosure read_verify_callback) {
-    EXPECT_TRUE(CheckData(block_number, read_buffer_->data(), kBlockSize));
-    std::move(read_verify_callback).Run();
-  }
-
-  // AppCacheResponseReader / Writer completion callbacks
-
-  void OnWriteInfoComplete(base::OnceClosure callback, int result) {
-    EXPECT_FALSE(writer_->IsWritePending());
-    EXPECT_EQ(expected_write_result_, result);
-    GetIOThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
-  }
-
-  void OnWriteComplete(CallbackMode callback_mode,
-                       base::OnceClosure callback,
-                       int result) {
-    EXPECT_FALSE(writer_->IsWritePending());
-    write_callback_was_called_ = true;
-    EXPECT_EQ(expected_write_result_, result);
-    if (should_delete_writer_in_completion_callback_ &&
-        --writer_deletion_count_down_ == 0) {
-      writer_.reset();
-    }
-
-    switch (callback_mode) {
-      case CallbackMode::kImmediate:
-        std::move(callback).Run();
-        break;
-      case CallbackMode::kPostTask:
-        GetIOThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
-    }
-  }
-
-  void OnMetadataWriteComplete(base::OnceClosure callback, int result) {
-    EXPECT_FALSE(metadata_writer_->IsWritePending());
-    EXPECT_EQ(expected_write_result_, result);
-    GetIOThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
-  }
-
-  void OnReadComplete(CallbackMode callback_mode,
-                      base::OnceClosure callback,
-                      int result) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_callback_was_called_ = true;
-    EXPECT_EQ(expected_read_result_, result);
-    if (should_delete_reader_in_completion_callback_ &&
-        --reader_deletion_count_down_ == 0) {
-      reader_.reset();
-    }
-
-    switch (callback_mode) {
-      case CallbackMode::kImmediate:
-        std::move(callback).Run();
-        break;
-      case CallbackMode::kPostTask:
-        GetIOThreadTaskRunner({})->PostTask(FROM_HERE, std::move(callback));
-    }
-  }
-
-  // Helpers to work with HttpResponseInfo objects
-
-  std::unique_ptr<net::HttpResponseInfo> MakeHttpResponseInfo(
-      const std::string& raw_headers) {
-    std::unique_ptr<net::HttpResponseInfo> info =
-        std::make_unique<net::HttpResponseInfo>();
-    info->request_time = base::Time::Now();
-    info->response_time = base::Time::Now();
-    info->was_cached = false;
-    info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
-    return info;
-  }
-
-  int GetHttpResponseInfoSize(const net::HttpResponseInfo& info) {
-    base::Pickle pickle = PickleHttpResonseInfo(info);
-    return pickle.size();
-  }
-
-  bool CompareHttpResponseInfos(const net::HttpResponseInfo& info1,
-                                const net::HttpResponseInfo& info2) {
-    base::Pickle pickle1 = PickleHttpResonseInfo(info1);
-    base::Pickle pickle2 = PickleHttpResonseInfo(info2);
-    return (pickle1.size() == pickle2.size()) &&
-           (0 == memcmp(pickle1.data(), pickle2.data(), pickle1.size()));
-  }
-
-  base::Pickle PickleHttpResonseInfo(const net::HttpResponseInfo& info) {
-    const bool kSkipTransientHeaders = true;
-    const bool kTruncated = false;
-    base::Pickle pickle;
-    info.Persist(&pickle, kSkipTransientHeaders, kTruncated);
-    return pickle;
-  }
-
-  // Helpers to fill and verify blocks of memory with a value
-
-  void FillData(char value, char* data, int data_len) {
-    memset(data, value, data_len);
-  }
-
-  bool CheckData(char value, const char* data, int data_len) {
-    for (int i = 0; i < data_len; ++i, ++data) {
-      if (*data != value)
-        return false;
-    }
-    return true;
-  }
-
-  // Individual Tests ---------------------------------------------------------
-  // Most of the individual tests involve multiple async steps. Each test
-  // is delineated with a section header.
-
-
-  // ReadNonExistentResponse -------------------------------------------
-  void ReadNonExistentResponse() {
-    // 1. Attempt to ReadInfo
-    // 2. Attempt to ReadData
-
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), kNoSuchResponseId);
-
-    base::RunLoop run_loop;
-    ReadNonExistentInfo(run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
-  void ReadNonExistentInfo(base::OnceClosure done_callback) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_info_buffer_ = base::MakeRefCounted<HttpResponseInfoIOBuffer>();
-    reader_->ReadInfo(
-        read_info_buffer_.get(),
-        base::BindOnce(&AppCacheResponseTest::OnReadNonExistentInfoComplete,
-                       base::Unretained(this), std::move(done_callback)));
-    EXPECT_TRUE(reader_->IsReadPending());
-    expected_read_result_ = net::ERR_CACHE_MISS;
-  }
-
-  void OnReadNonExistentInfoComplete(base::OnceClosure done_callback,
-                                     int result) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    EXPECT_EQ(expected_read_result_, result);
-    GetIOThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheResponseTest::ReadNonExistentData,
-                       base::Unretained(this), std::move(done_callback)));
-  }
-
-  void ReadNonExistentData(base::OnceClosure callback) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_buffer_ = base::MakeRefCounted<IOBuffer>(kBlockSize);
-    reader_->ReadData(
-        read_buffer_.get(), kBlockSize,
-        base::BindOnce(&AppCacheResponseTest::OnReadComplete,
-                       base::Unretained(this), CallbackMode::kPostTask,
-                       std::move(callback)));
-    EXPECT_TRUE(reader_->IsReadPending());
-    expected_read_result_ = net::ERR_CACHE_MISS;
-  }
-
-  // LoadResponseInfo_Miss ----------------------------------------------------
-  void LoadResponseInfo_Miss() {
-    base::RunLoop run_loop;
-    MockStorageDelegate storage_delegate(this, run_loop.QuitClosure());
-    service_->storage()->LoadResponseInfo(GURL(), kNoSuchResponseId,
-                                          &storage_delegate);
-    run_loop.Run();
-
-    LoadResponseInfo_Miss_Verify(storage_delegate);
-  }
-
-  void LoadResponseInfo_Miss_Verify(MockStorageDelegate& storage_delegate) {
-    EXPECT_EQ(kNoSuchResponseId, storage_delegate.loaded_info_id_);
-    EXPECT_TRUE(!storage_delegate.loaded_info_.get());
-  }
-
-  // LoadResponseInfo_Hit ----------------------------------------------------
-  void LoadResponseInfo_Hit() {
-    // This tests involves multiple async steps.
-    // 1. Write a response headers and body to storage
-    //   a. headers
-    //   b. body
-    // 2. Use LoadResponseInfo to read the response headers back out
-    writer_ = service_->storage()->CreateResponseWriter(GURL());
-    written_response_id_ = writer_->response_id();
-
-    base::RunLoop run_loop;
-    MockStorageDelegate storage_delegate(this, run_loop.QuitClosure());
-    WriteBasicResponse(base::BindLambdaForTesting([&]() {
-      writer_.reset();
-      service_->storage()->LoadResponseInfo(GURL(), written_response_id_,
-                                            &storage_delegate);
-    }));
-    run_loop.Run();
-
-    LoadResponseInfo_Hit_Verify(storage_delegate);
-  }
-
-  void LoadResponseInfo_Hit_Verify(MockStorageDelegate& storage_delegate) {
-    EXPECT_EQ(written_response_id_, storage_delegate.loaded_info_id_);
-    EXPECT_TRUE(storage_delegate.loaded_info_.get());
-    EXPECT_TRUE(CompareHttpResponseInfos(
-        *write_info_buffer_->http_info,
-        storage_delegate.loaded_info_->http_response_info()));
-    EXPECT_EQ(basic_response_size(),
-              storage_delegate.loaded_info_->response_data_size());
-  }
-
-  // Metadata -------------------------------------------------
-  void Metadata() {
-    // This tests involves multiple async steps.
-    // 1. Write a response headers and body to storage
-    //   a. headers
-    //   b. body
-    // 2. Write metadata "Metadata First" using AppCacheResponseMetadataWriter.
-    // 3. Check metadata was written.
-    // 4. Write metadata "Second".
-    // 5. Check metadata was written and was truncated .
-    // 6. Write metadata "".
-    // 7. Check metadata was deleted.
-
-    writer_ = service_->storage()->CreateResponseWriter(GURL());
-    written_response_id_ = writer_->response_id();
-
-    {
-      base::RunLoop run_loop;
-      WriteBasicResponse(
-          base::BindOnce(&AppCacheResponseTest::Metadata_ResetWriter,
-                         base::Unretained(this), run_loop.QuitClosure()));
-      run_loop.Run();
-    }
-
-    Metadata_WriteLoadVerify("Metadata first");
-    Metadata_WriteLoadVerify("Second");
-    Metadata_WriteLoadVerify("");
-  }
-
-  void Metadata_ResetWriter(base::OnceClosure done_callback) {
-    writer_.reset();
-    std::move(done_callback).Run();
-  }
-
-  void Metadata_WriteLoadVerify(const char* metadata) {
-    base::RunLoop run_loop;
-    MockStorageDelegate storage_delegate(this, run_loop.QuitClosure());
-
-    Metadata_WriteMetadata("Metadata First", base::BindLambdaForTesting([&]() {
-                             metadata_writer_.reset();
-                             service_->storage()->LoadResponseInfo(
-                                 GURL(), written_response_id_,
-                                 &storage_delegate);
-                           }));
-    run_loop.Run();
-  }
-
-  void Metadata_WriteMetadata(const char* metadata,
-                              base::OnceClosure callback) {
-    metadata_writer_ =
-        service_->storage()->CreateResponseMetadataWriter(written_response_id_);
-    scoped_refptr<IOBuffer> buffer =
-        base::MakeRefCounted<WrappedIOBuffer>(metadata);
-    WriteResponseMetadata(buffer.get(), strlen(metadata), std::move(callback));
-  }
-
-  void Metadata_VerifyMetadata(const char* metadata,
-                               MockStorageDelegate& storage_delegate) {
-    EXPECT_EQ(written_response_id_, storage_delegate.loaded_info_id_);
-    EXPECT_TRUE(storage_delegate.loaded_info_.get());
-    EXPECT_TRUE(CompareHttpResponseInfos(
-        *write_info_buffer_->http_info,
-        storage_delegate.loaded_info_->http_response_info()));
-    EXPECT_EQ(basic_response_size(),
-              storage_delegate.loaded_info_->response_data_size());
-  }
-
-  // AmountWritten ----------------------------------------------------
-
-  void AmountWritten() {
-    static const char kHttpHeaders[] = "HTTP/1.0 200 OK\0\0";
-    std::string raw_headers(kHttpHeaders, base::size(kHttpHeaders));
-    std::unique_ptr<net::HttpResponseInfo> head =
-        MakeHttpResponseInfo(raw_headers);
-    int expected_amount_written =
-        GetHttpResponseInfoSize(*head) + kNumBlocks * kBlockSize;
-
-    // Build callbacks in reverse order.
-    base::RunLoop run_loop;
-    base::OnceClosure callback = run_loop.QuitClosure();
-    for (int i = 0; i < kNumBlocks; ++i) {
-      callback = base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
-                                base::Unretained(this), kNumBlocks - i,
-                                CallbackMode::kPostTask, std::move(callback));
-    }
-
-    writer_ = service_->storage()->CreateResponseWriter(GURL());
-    written_response_id_ = writer_->response_id();
-    GetIOThreadTaskRunner({})->PostTask(
-        FROM_HERE, base::BindOnce(&AppCacheResponseTest::WriteResponseHead,
-                                  base::Unretained(this), std::move(head),
-                                  std::move(callback)));
-    run_loop.Run();
-
-    Verify_AmountWritten(expected_amount_written);
-  }
-
-  void Verify_AmountWritten(int expected_amount_written) {
-    EXPECT_EQ(expected_amount_written, writer_->amount_written());
-  }
-
-  // WriteThenVariouslyReadResponse -------------------------------------------
-
-  void WriteThenVariouslyReadResponse() {
-    // This tests involves multiple async steps.
-    // 1. First, write a large body using multiple writes, we don't bother
-    //    with a response head for this test.
-    // 2. Read the entire body, using multiple reads
-    // 3. Read the entire body, using one read.
-    // 4. Attempt to read beyond the EOF.
-    // 5. Read just a range.
-    // 6. Attempt to read beyond EOF of a range.
-
-    // Push tasks in reverse order
-    base::RunLoop run_loop;
-    GetIOThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheResponseTest::
-                           WriteThenVariouslyReadResponse_WriteOutReadInBlocks,
-                       base::Unretained(this), run_loop.QuitClosure()));
-    run_loop.Run();
-  }
-
-  void WriteThenVariouslyReadResponse_WriteOutReadInBlocks(
-      base::OnceClosure done_callback) {
-    WriteOutBlocks(base::BindOnce(
-        &AppCacheResponseTest::ReadInBlocks, base::Unretained(this),
-        base::BindOnce(&AppCacheResponseTest::ReadAllAtOnce,
-                       base::Unretained(this), std::move(done_callback))));
-  }
-
-  void ReadAllAtOnce(base::OnceClosure done_callback) {
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    int big_size = kNumBlocks * kBlockSize;
-    ReadResponseBody(
-        base::MakeRefCounted<IOBuffer>(big_size), big_size,
-        CallbackMode::kPostTask,
-        base::BindOnce(&AppCacheResponseTest::VerifyAllAtOnce,
-                       base::Unretained(this), std::move(done_callback)));
-  }
-
-  void VerifyAllAtOnce(base::OnceClosure done_callback) {
-    char* p = read_buffer_->data();
-    for (int i = 0; i < kNumBlocks; ++i, p += kBlockSize)
-      EXPECT_TRUE(CheckData(i + 1, p, kBlockSize));
-    ReadPastEOF(std::move(done_callback));
-  }
-
-  void ReadPastEOF(base::OnceClosure done_callback) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_buffer_ = base::MakeRefCounted<IOBuffer>(kBlockSize);
-    expected_read_result_ = 0;
-    reader_->ReadData(
-        read_buffer_.get(), kBlockSize,
-        base::BindOnce(
-            &AppCacheResponseTest::OnReadComplete, base::Unretained(this),
-            CallbackMode::kPostTask,
-            base::BindOnce(&AppCacheResponseTest::ReadRange,
-                           base::Unretained(this), std::move(done_callback))));
-  }
-
-  void ReadRange(base::OnceClosure done_callback) {
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    reader_->SetReadRange(kBlockSize, kBlockSize);
-    ReadResponseBody(
-        base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize,
-        CallbackMode::kPostTask,
-        base::BindOnce(
-            &AppCacheResponseTest::VerifyRange, base::Unretained(this),
-            base::BindOnce(&AppCacheResponseTest::ReadPastRangeEnd,
-                           base::Unretained(this), std::move(done_callback))));
-  }
-
-  void VerifyRange(base::OnceClosure verify_callback) {
-    EXPECT_TRUE(CheckData(2, read_buffer_->data(), kBlockSize));
-    std::move(verify_callback).Run();
-  }
-
-  void ReadPastRangeEnd(base::OnceClosure done_callback) {
-    EXPECT_FALSE(reader_->IsReadPending());
-    read_buffer_ = base::MakeRefCounted<IOBuffer>(kBlockSize);
-    expected_read_result_ = 0;
-    reader_->ReadData(
-        read_buffer_.get(), kBlockSize,
-        base::BindOnce(
-            &AppCacheResponseTest::OnReadComplete, base::Unretained(this),
-            CallbackMode::kPostTask,
-            base::BindOnce(&AppCacheResponseTest::ReadRangePartiallyBeyondEOF,
-                           base::Unretained(this), std::move(done_callback))));
-  }
-
-  void ReadRangePartiallyBeyondEOF(base::OnceClosure done_callback) {
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    reader_->SetReadRange(kBlockSize, kNumBlocks * kBlockSize);
-    ReadResponseBody(
-        base::MakeRefCounted<IOBuffer>(kNumBlocks * kBlockSize),
-        kNumBlocks * kBlockSize, CallbackMode::kPostTask,
-        base::BindOnce(
-            &AppCacheResponseTest::VerifyRangeBeyondEOF, base::Unretained(this),
-            base::BindOnce(&AppCacheResponseTest::ReadRangeFullyBeyondEOF,
-                           base::Unretained(this), std::move(done_callback))));
-    expected_read_result_ = (kNumBlocks - 1) * kBlockSize;
-  }
-
-  void VerifyRangeBeyondEOF(base::OnceClosure verify_callback) {
-    // Just verify the first 1k
-    VerifyRange(std::move(verify_callback));
-  }
-
-  void ReadRangeFullyBeyondEOF(base::OnceClosure done_callback) {
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    reader_->SetReadRange((kNumBlocks * kBlockSize) + 1, kBlockSize);
-    ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize,
-                     CallbackMode::kPostTask, std::move(done_callback));
-    expected_read_result_ = 0;
-  }
-
-  // IOChaining -------------------------------------------
-  void IOChaining() {
-    // 1. Write several blocks out initiating the subsequent write
-    //    from within the completion callback of the previous write.
-    // 2. Read and verify several blocks in similarly chaining reads.
-
-    base::RunLoop run_loop;
-    WriteOutBlocksImmediately(run_loop.QuitClosure());
-    run_loop.Run();
-  }
-
-  void WriteOutBlocksImmediately(base::OnceClosure done_callback) {
-    writer_ = service_->storage()->CreateResponseWriter(GURL());
-    written_response_id_ = writer_->response_id();
-
-    base::OnceClosure callback =
-        base::BindOnce(&AppCacheResponseTest::ReadInBlocksImmediately,
-                       base::Unretained(this), std::move(done_callback));
-    for (int i = 0; i < kNumBlocks; ++i) {
-      callback = base::BindOnce(&AppCacheResponseTest::WriteOneBlock,
-                                base::Unretained(this), kNumBlocks - i,
-                                CallbackMode::kImmediate, std::move(callback));
-    }
-    std::move(callback).Run();
-  }
-
-  void ReadInBlocksImmediately(base::OnceClosure done_callback) {
-    writer_.reset();
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-
-    base::OnceClosure callback = std::move(done_callback);
-    for (int i = 0; i < kNumBlocks; ++i) {
-      callback = base::BindOnce(&AppCacheResponseTest::ReadOneBlockImmediately,
-                                base::Unretained(this), kNumBlocks - i,
-                                std::move(callback));
-    }
-    std::move(callback).Run();
-  }
-
-  void ReadOneBlockImmediately(int block_number, base::OnceClosure callback) {
-    ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize,
-                     CallbackMode::kImmediate,
-                     base::BindOnce(&AppCacheResponseTest::VerifyOneBlock,
-                                    base::Unretained(this), block_number,
-                                    std::move(callback)));
-  }
-
-  // DeleteWithinCallbacks -------------------------------------------
-  void DeleteWithinCallbacks() {
-    // 1. Write out a few blocks normally, and upon
-    //    completion of the last write, delete the writer.
-    // 2. Read in a few blocks normally, and upon completion
-    //    of the last read, delete the reader.
-
-    should_delete_reader_in_completion_callback_ = true;
-    reader_deletion_count_down_ = kNumBlocks;
-    should_delete_writer_in_completion_callback_ = true;
-    writer_deletion_count_down_ = kNumBlocks;
-
-    base::RunLoop run_loop;
-    WriteOutBlocks(base::BindOnce(&AppCacheResponseTest::ReadInBlocks,
-                                  base::Unretained(this),
-                                  run_loop.QuitClosure()));
-    run_loop.Run();
-  }
-
-  // DeleteWithIOPending -------------------------------------------
-  void DeleteWithIOPending() {
-    // 1. Write a few blocks normally.
-    // 2. Start a write, delete with it pending.
-    // 3. Start a read, delete with it pending.
-
-    base::RunLoop run_loop;
-    WriteOutBlocks(base::BindOnce(&AppCacheResponseTest::WriteThenDelete,
-                                  base::Unretained(this),
-                                  run_loop.QuitClosure()));
-    run_loop.Run();
-  }
-
-  void WriteThenDelete(base::OnceClosure done_callback) {
-    write_callback_was_called_ = false;
-    WriteOneBlock(5, CallbackMode::kPostTask, base::DoNothing());
-    EXPECT_TRUE(writer_->IsWritePending());
-    writer_.reset();
-
-    GetIOThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheResponseTest::ReadThenDelete,
-                       base::Unretained(this), std::move(done_callback)));
-  }
-
-  void ReadThenDelete(base::OnceClosure done_callback) {
-    read_callback_was_called_ = false;
-    reader_ =
-        service_->storage()->CreateResponseReader(GURL(), written_response_id_);
-    ReadResponseBody(base::MakeRefCounted<IOBuffer>(kBlockSize), kBlockSize,
-                     CallbackMode::kImmediate, base::DoNothing());
-    EXPECT_TRUE(reader_->IsReadPending());
-    reader_.reset();
-
-    // Wait a moment to verify no callbacks.
-    GetIOThreadTaskRunner({})->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheResponseTest::VerifyNoCallbacks,
-                       base::Unretained(this), std::move(done_callback)),
-        base::TimeDelta::FromMilliseconds(10));
-  }
-
-  void VerifyNoCallbacks(base::OnceClosure done_callback) {
-    EXPECT_TRUE(!write_callback_was_called_);
-    EXPECT_TRUE(!read_callback_was_called_);
-    std::move(done_callback).Run();
-  }
-
-  // Data members
-
-  std::unique_ptr<content::BrowserTaskEnvironment> task_environment_;
-
-  std::unique_ptr<MockAppCacheService> service_;
-
-  std::unique_ptr<AppCacheResponseReader> reader_;
-  scoped_refptr<HttpResponseInfoIOBuffer> read_info_buffer_;
-  scoped_refptr<IOBuffer> read_buffer_;
-  int expected_read_result_ = 0;
-  bool should_delete_reader_in_completion_callback_ = false;
-  int reader_deletion_count_down_ = 0;
-  bool read_callback_was_called_ = false;
-
-  int64_t written_response_id_ = 0;
-  std::unique_ptr<AppCacheResponseWriter> writer_;
-  std::unique_ptr<AppCacheResponseMetadataWriter> metadata_writer_;
-  scoped_refptr<HttpResponseInfoIOBuffer> write_info_buffer_;
-  scoped_refptr<IOBuffer> write_buffer_;
-  int expected_write_result_ = 0;
-  bool should_delete_writer_in_completion_callback_ = false;
-  int writer_deletion_count_down_ = 0;
-  bool write_callback_was_called_ = false;
-};
-
-TEST_F(AppCacheResponseTest, ReadNonExistentResponse) {
-  RunTestOnIOThread(&AppCacheResponseTest::ReadNonExistentResponse);
-}
-
-TEST_F(AppCacheResponseTest, LoadResponseInfo_Miss) {
-  RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Miss);
-}
-
-TEST_F(AppCacheResponseTest, LoadResponseInfo_Hit) {
-  RunTestOnIOThread(&AppCacheResponseTest::LoadResponseInfo_Hit);
-}
-
-TEST_F(AppCacheResponseTest, Metadata) {
-  RunTestOnIOThread(&AppCacheResponseTest::Metadata);
-}
-
-TEST_F(AppCacheResponseTest, AmountWritten) {
-  RunTestOnIOThread(&AppCacheResponseTest::AmountWritten);
-}
-
-TEST_F(AppCacheResponseTest, WriteThenVariouslyReadResponse) {
-  RunTestOnIOThread(&AppCacheResponseTest::WriteThenVariouslyReadResponse);
-}
-
-TEST_F(AppCacheResponseTest, IOChaining) {
-  RunTestOnIOThread(&AppCacheResponseTest::IOChaining);
-}
-
-TEST_F(AppCacheResponseTest, DeleteWithinCallbacks) {
-  RunTestOnIOThread(&AppCacheResponseTest::DeleteWithinCallbacks);
-}
-
-TEST_F(AppCacheResponseTest, DeleteWithIOPending) {
-  RunTestOnIOThread(&AppCacheResponseTest::DeleteWithIOPending);
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_service_unittest.cc b/content/browser/appcache/appcache_service_unittest.cc
deleted file mode 100644
index 53ce001..0000000
--- a/content/browser/appcache/appcache_service_unittest.cc
+++ /dev/null
@@ -1,395 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/cxx17_backports.h"
-#include "base/location.h"
-#include "base/pickle.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/appcache_service_impl.h"
-#include "content/browser/appcache/mock_appcache_storage.h"
-#include "content/public/test/browser_task_environment.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/io_buffer.h"
-#include "net/http/http_response_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-
-namespace content {
-namespace {
-
-const int64_t kMockGroupId = 1;
-const int64_t kMockCacheId = 1;
-const int64_t kMockResponseId = 1;
-const int64_t kMissingCacheId = 5;
-const int64_t kMissingResponseId = 5;
-const char kMockHeaders[] =
-    "HTTP/1.0 200 OK\0Content-Length: 5\0\0";
-const char kMockBody[] = "Hello";
-const int kMockBodySize = 5;
-
-class MockResponseReader : public AppCacheResponseReader {
- public:
-  MockResponseReader(int64_t response_id,
-                     std::unique_ptr<net::HttpResponseInfo> info,
-                     int info_size,
-                     const char* data,
-                     int data_size)
-      : AppCacheResponseReader(response_id, /*disk_cache=*/nullptr),
-        info_(std::move(info)),
-        info_size_(info_size),
-        data_(data),
-        data_size_(data_size) {}
-  void ReadInfo(HttpResponseInfoIOBuffer* info_buf,
-                net::CompletionOnceCallback callback) override {
-    info_buffer_ = info_buf;
-    callback_ = std::move(callback);  // Cleared on completion.
-
-    int rv = info_.get() ? info_size_ : net::ERR_FAILED;
-    info_buffer_->http_info = std::move(info_);
-    info_buffer_->response_data_size = data_size_;
-    ScheduleUserCallback(rv);
-  }
-  void ReadData(net::IOBuffer* buf,
-                int buf_len,
-                net::CompletionOnceCallback callback) override {
-    buffer_ = buf;
-    buffer_len_ = buf_len;
-    callback_ = std::move(callback);  // Cleared on completion.
-
-    if (!data_) {
-      ScheduleUserCallback(net::ERR_CACHE_READ_FAILURE);
-      return;
-    }
-    DCHECK(buf_len >= data_size_);
-    memcpy(buf->data(), data_, data_size_);
-    ScheduleUserCallback(data_size_);
-    data_size_ = 0;
-  }
-
- private:
-  void ScheduleUserCallback(int result) {
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&MockResponseReader::InvokeUserCompletionCallback,
-                       weak_factory_.GetWeakPtr(), result));
-  }
-
-  std::unique_ptr<net::HttpResponseInfo> info_;
-  int info_size_;
-  const char* data_;
-  int data_size_;
-};
-
-}  // namespace
-
-
-class AppCacheServiceImplTest : public testing::Test {
- public:
-  AppCacheServiceImplTest()
-      : kOriginURL("http://hello/"),
-        kOrigin(url::Origin::Create(kOriginURL)),
-        kManifestUrl(kOriginURL.Resolve("manifest")),
-        service_(std::make_unique<AppCacheServiceImpl>(nullptr, nullptr)),
-        delete_result_(net::OK),
-        delete_completion_count_(0) {
-    // Setup to use mock storage.
-    service_->storage_ = std::make_unique<MockAppCacheStorage>(service_.get());
-  }
-
-  void OnDeleteAppCachesComplete(int result) {
-    delete_result_ = result;
-    ++delete_completion_count_;
-  }
-
-  MockAppCacheStorage* mock_storage() {
-    return static_cast<MockAppCacheStorage*>(service_->storage());
-  }
-
-  void ResetStorage() {
-    service_->storage_ = std::make_unique<MockAppCacheStorage>(service_.get());
-  }
-
-  bool IsGroupStored(const GURL& manifest_url) {
-    return mock_storage()->IsGroupForManifestStored(manifest_url);
-  }
-
-  int CountPendingHelpers() {
-    return service_->pending_helpers_.size();
-  }
-
-  void SetupMockGroup() {
-    std::unique_ptr<net::HttpResponseInfo> info(MakeMockResponseInfo());
-    const int kMockInfoSize = GetResponseInfoSize(info.get());
-
-    // Create a mock group, cache, and entry and stuff them into mock storage.
-    auto group = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), kManifestUrl, kMockGroupId);
-    auto cache =
-        base::MakeRefCounted<AppCache>(service_->storage(), kMockCacheId);
-    cache->AddEntry(
-        kManifestUrl,
-        AppCacheEntry(AppCacheEntry::MANIFEST, kMockResponseId,
-                      kMockInfoSize + kMockBodySize, /*padding_size=*/0));
-    cache->set_complete(true);
-    group->AddCache(cache.get());
-    mock_storage()->AddStoredGroup(group.get());
-    mock_storage()->AddStoredCache(cache.get());
-  }
-
-  void SetupMockReader(
-      bool valid_info, bool valid_data, bool valid_size) {
-    std::unique_ptr<net::HttpResponseInfo> info =
-        valid_info ? MakeMockResponseInfo() : nullptr;
-    int info_size = info ? GetResponseInfoSize(info.get()) : 0;
-    const char* data = valid_data ? kMockBody : nullptr;
-    int data_size = valid_size ? kMockBodySize : 3;
-    mock_storage()->SimulateResponseReader(std::make_unique<MockResponseReader>(
-        kMockResponseId, std::move(info), info_size, data, data_size));
-  }
-
-  std::unique_ptr<net::HttpResponseInfo> MakeMockResponseInfo() {
-    auto info = std::make_unique<net::HttpResponseInfo>();
-    info->request_time = base::Time::Now();
-    info->response_time = base::Time::Now();
-    info->was_cached = false;
-    info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(kMockHeaders, base::size(kMockHeaders)));
-    return info;
-  }
-
-  int GetResponseInfoSize(const net::HttpResponseInfo* info) {
-    base::Pickle pickle;
-    return PickleResponseInfo(&pickle, info);
-  }
-
-  int PickleResponseInfo(base::Pickle* pickle,
-                         const net::HttpResponseInfo* info) {
-    const bool kSkipTransientHeaders = true;
-    const bool kTruncated = false;
-    info->Persist(pickle, kSkipTransientHeaders, kTruncated);
-    return pickle->size();
-  }
-
-  net::CompletionOnceCallback deletion_callback() {
-    return base::BindOnce(&AppCacheServiceImplTest::OnDeleteAppCachesComplete,
-                          base::Unretained(this));
-  }
-
-  const GURL kOriginURL;
-  const url::Origin kOrigin;
-  const GURL kManifestUrl;
-
-  BrowserTaskEnvironment task_environment_;
-  std::unique_ptr<AppCacheServiceImpl> service_;
-  int delete_result_;
-  int delete_completion_count_;
-};
-
-TEST_F(AppCacheServiceImplTest, DeleteAppCachesForOrigin) {
-  // Without giving mock storage simiulated info, should fail.
-  service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
-  EXPECT_EQ(0, delete_completion_count_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, delete_completion_count_);
-  EXPECT_EQ(net::ERR_FAILED, delete_result_);
-  delete_completion_count_ = 0;
-
-  // Should succeed given an empty info collection.
-  mock_storage()->SimulateGetAllInfo(
-      base::MakeRefCounted<content::AppCacheInfoCollection>());
-  service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
-  EXPECT_EQ(0, delete_completion_count_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, delete_completion_count_);
-  EXPECT_EQ(net::OK, delete_result_);
-  delete_completion_count_ = 0;
-
-  auto info = base::MakeRefCounted<AppCacheInfoCollection>();
-
-  // Should succeed given a non-empty info collection.
-  blink::mojom::AppCacheInfo mock_manifest_1;
-  blink::mojom::AppCacheInfo mock_manifest_2;
-  blink::mojom::AppCacheInfo mock_manifest_3;
-  mock_manifest_1.manifest_url = kOriginURL.Resolve("manifest1");
-  mock_manifest_2.manifest_url = kOriginURL.Resolve("manifest2");
-  mock_manifest_3.manifest_url = kOriginURL.Resolve("manifest3");
-  std::vector<blink::mojom::AppCacheInfo> info_vector;
-  info_vector.push_back(mock_manifest_1);
-  info_vector.push_back(mock_manifest_2);
-  info_vector.push_back(mock_manifest_3);
-  info->infos_by_origin[kOrigin] = info_vector;
-  mock_storage()->SimulateGetAllInfo(info.get());
-  service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
-  EXPECT_EQ(0, delete_completion_count_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, delete_completion_count_);
-  EXPECT_EQ(net::OK, delete_result_);
-  delete_completion_count_ = 0;
-
-  // Should fail if storage fails to delete.
-  info->infos_by_origin[kOrigin] = info_vector;
-  mock_storage()->SimulateGetAllInfo(info.get());
-  mock_storage()->SimulateMakeGroupObsoleteFailure();
-  service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
-  EXPECT_EQ(0, delete_completion_count_);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, delete_completion_count_);
-  EXPECT_EQ(net::ERR_FAILED, delete_result_);
-  delete_completion_count_ = 0;
-
-  // Should complete with abort error if the service is deleted
-  // prior to a delete completion.
-  service_->DeleteAppCachesForOrigin(kOrigin, deletion_callback());
-  EXPECT_EQ(0, delete_completion_count_);
-  service_.reset();  // kill it
-  EXPECT_EQ(1, delete_completion_count_);
-  EXPECT_EQ(net::ERR_ABORTED, delete_result_);
-  delete_completion_count_ = 0;
-
-  // Let any tasks lingering from the sudden deletion run and verify
-  // no other completion calls occur.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, delete_completion_count_);
-}
-
-TEST_F(AppCacheServiceImplTest, CheckAppCacheResponse) {
-  // Check a non-existing manifest.
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  service_->CheckAppCacheResponse(kManifestUrl, 1, 1);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response that looks good.
-  // Nothing should be deleted.
-  SetupMockGroup();
-  EXPECT_TRUE(IsGroupStored(kManifestUrl));
-  SetupMockReader(true, true, true);
-  service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_TRUE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response for which there is no cache entry.
-  // The group should get deleted.
-  SetupMockGroup();
-  service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId,
-                                  kMissingResponseId);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response for which there is no manifest entry in a newer version
-  // of the cache. Nothing should get deleted in this case.
-  SetupMockGroup();
-  service_->CheckAppCacheResponse(kManifestUrl, kMissingCacheId,
-                                  kMissingResponseId);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_TRUE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response with bad headers.
-  SetupMockGroup();
-  service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId);
-  SetupMockReader(false, true, true);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response with bad data.
-  SetupMockGroup();
-  service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId);
-  SetupMockReader(true, false, true);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  // Check a response with truncated data.
-  SetupMockGroup();
-  service_->CheckAppCacheResponse(kManifestUrl, kMockCacheId, kMockResponseId);
-  SetupMockReader(true, true, false);
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(0, CountPendingHelpers());
-  EXPECT_FALSE(IsGroupStored(kManifestUrl));
-  ResetStorage();
-
-  service_.reset();  // Clean up.
-  base::RunLoop().RunUntilIdle();
-}
-
-// Just tests the backoff scheduling function, not the actual reinit function.
-TEST_F(AppCacheServiceImplTest, ScheduleReinitialize) {
-  const base::TimeDelta kNoDelay;
-  const base::TimeDelta kOneSecond(base::TimeDelta::FromSeconds(1));
-  const base::TimeDelta k30Seconds(base::TimeDelta::FromSeconds(30));
-  const base::TimeDelta kOneHour(base::TimeDelta::FromHours(1));
-
-  // Do things get initialized as expected?
-  auto service = std::make_unique<AppCacheServiceImpl>(nullptr, nullptr);
-  EXPECT_TRUE(service->last_reinit_time_.is_null());
-  EXPECT_FALSE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(kNoDelay, service->next_reinit_delay_);
-
-  // Do we see artifacts of the timer pending and such?
-  service->ScheduleReinitialize();
-  EXPECT_TRUE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay());
-  EXPECT_EQ(k30Seconds, service->next_reinit_delay_);
-
-  // Nothing should change if already scheduled
-  service->ScheduleReinitialize();
-  EXPECT_TRUE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay());
-  EXPECT_EQ(k30Seconds, service->next_reinit_delay_);
-
-  // Does the delay increase as expected?
-  service->reinit_timer_.Stop();
-  service->last_reinit_time_ = base::Time::Now() - kOneSecond;
-  service->ScheduleReinitialize();
-  EXPECT_TRUE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(k30Seconds, service->reinit_timer_.GetCurrentDelay());
-  EXPECT_EQ(k30Seconds + k30Seconds, service->next_reinit_delay_);
-
-  // Does the delay reset as expected?
-  service->reinit_timer_.Stop();
-  service->last_reinit_time_ = base::Time::Now() -
-                               base::TimeDelta::FromHours(2);
-  service->ScheduleReinitialize();
-  EXPECT_TRUE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(kNoDelay, service->reinit_timer_.GetCurrentDelay());
-  EXPECT_EQ(k30Seconds, service->next_reinit_delay_);
-
-  // Does the delay max out as expected?
-  service->reinit_timer_.Stop();
-  service->last_reinit_time_ = base::Time::Now() - kOneSecond;
-  service->next_reinit_delay_ = kOneHour;
-  service->ScheduleReinitialize();
-  EXPECT_TRUE(service->reinit_timer_.IsRunning());
-  EXPECT_EQ(kOneHour, service->reinit_timer_.GetCurrentDelay());
-  EXPECT_EQ(kOneHour, service->next_reinit_delay_);
-
-  // Fine to delete while pending.
-  service.reset(nullptr);
-}
-
-
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_storage_impl_unittest.cc b/content/browser/appcache/appcache_storage_impl_unittest.cc
deleted file mode 100644
index 7d5e2e7..0000000
--- a/content/browser/appcache/appcache_storage_impl_unittest.cc
+++ /dev/null
@@ -1,2056 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_storage_impl.h"
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/callback_helpers.h"
-#include "base/containers/stack.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/message_loop/message_pump_type.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/bind.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_database.h"
-#include "content/browser/appcache/appcache_entry.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_host.h"
-#include "content/browser/appcache/appcache_request.h"
-#include "content/browser/appcache/appcache_request_handler.h"
-#include "content/browser/appcache/appcache_service_impl.h"
-#include "content/browser/appcache/mock_appcache_policy.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/url_loader_interceptor.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
-#include "services/network/test/test_utils.h"
-#include "sql/test/test_helpers.h"
-#include "storage/browser/quota/quota_client_type.h"
-#include "storage/browser/quota/quota_manager.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/storage_key/storage_key.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-namespace content {
-
-using blink::mojom::StorageType;
-
-namespace {
-
-constexpr int kMockProcessId = 1;
-constexpr int kMockQuota = 5000;
-
-// The Reinitialize test needs some http accessible resources to run,
-// we mock stuff inprocess for that.
-static GURL GetMockUrl(const std::string& path) {
-  return GURL("http://mockhost/" + path);
-}
-
-const int kProcessId = 1;
-std::unique_ptr<base::Thread> background_thread;
-
-bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) {
-  if (params->url_request.url == GetMockUrl("manifest")) {
-    URLLoaderInterceptor::WriteResponse("", "CACHE MANIFEST\n",
-                                        params->client.get());
-    return true;
-  } else if (params->url_request.url == GetMockUrl("empty.html")) {
-    URLLoaderInterceptor::WriteResponse("", "", params->client.get());
-    return true;
-  }
-  return false;
-}
-
-}  // namespace
-
-class AppCacheStorageImplTest : public testing::Test {
- public:
-  class MockStorageDelegate : public AppCacheStorage::Delegate {
-   public:
-    explicit MockStorageDelegate(AppCacheStorageImplTest* test)
-        : loaded_cache_id_(0),
-          stored_group_success_(false),
-          would_exceed_quota_(false),
-          obsoleted_success_(false),
-          found_cache_id_(blink::mojom::kAppCacheNoCacheId),
-          test_(test) {}
-
-    void OnCacheLoaded(AppCache* cache, int64_t cache_id) override {
-      loaded_cache_ = cache;
-      loaded_cache_id_ = cache_id;
-      test_->ScheduleNextTask();
-    }
-
-    void OnGroupLoaded(AppCacheGroup* group,
-                       const GURL& manifest_url) override {
-      loaded_group_ = group;
-      loaded_manifest_url_ = manifest_url;
-      loaded_groups_newest_cache_ =
-          group ? group->newest_complete_cache() : nullptr;
-      test_->ScheduleNextTask();
-    }
-
-    void OnGroupAndNewestCacheStored(AppCacheGroup* group,
-                                     AppCache* newest_cache,
-                                     bool success,
-                                     bool would_exceed_quota) override {
-      stored_group_ = group;
-      stored_group_success_ = success;
-      would_exceed_quota_ = would_exceed_quota;
-      test_->ScheduleNextTask();
-    }
-
-    void OnGroupMadeObsolete(AppCacheGroup* group,
-                             bool success,
-                             int response_code) override {
-      obsoleted_group_ = group;
-      obsoleted_success_ = success;
-      test_->ScheduleNextTask();
-    }
-
-    void OnMainResponseFound(const GURL& url,
-                             const AppCacheEntry& entry,
-                             const GURL& namespace_entry_url,
-                             const AppCacheEntry& fallback_entry,
-                             int64_t cache_id,
-                             int64_t group_id,
-                             const GURL& manifest_url) override {
-      found_url_ = url;
-      found_entry_ = entry;
-      found_namespace_entry_url_ = namespace_entry_url;
-      found_fallback_entry_ = fallback_entry;
-      found_cache_id_ = cache_id;
-      found_group_id_ = group_id;
-      found_manifest_url_ = manifest_url;
-      test_->ScheduleNextTask();
-    }
-
-    scoped_refptr<AppCache> loaded_cache_;
-    int64_t loaded_cache_id_;
-    scoped_refptr<AppCacheGroup> loaded_group_;
-    GURL loaded_manifest_url_;
-    scoped_refptr<AppCache> loaded_groups_newest_cache_;
-    scoped_refptr<AppCacheGroup> stored_group_;
-    bool stored_group_success_;
-    bool would_exceed_quota_;
-    scoped_refptr<AppCacheGroup> obsoleted_group_;
-    bool obsoleted_success_;
-    GURL found_url_;
-    AppCacheEntry found_entry_;
-    GURL found_namespace_entry_url_;
-    AppCacheEntry found_fallback_entry_;
-    int64_t found_cache_id_;
-    int64_t found_group_id_;
-    GURL found_manifest_url_;
-    AppCacheStorageImplTest* test_;
-  };
-
-  class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
-   public:
-    MockQuotaManagerProxy()
-        : QuotaManagerProxy(nullptr, base::SequencedTaskRunnerHandle::Get()) {}
-
-    void NotifyStorageAccessed(const blink::StorageKey& storage_key,
-                               StorageType type,
-                               base::Time access_time) override {
-      EXPECT_EQ(StorageType::kTemporary, type);
-      ++notify_storage_accessed_count_;
-      last_storage_key_ = storage_key;
-    }
-
-    void NotifyStorageModified(
-        storage::QuotaClientType client_id,
-        const blink::StorageKey& storage_key,
-        StorageType type,
-        int64_t delta,
-        base::Time modification_time,
-        scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-        base::OnceClosure callback) override {
-      EXPECT_EQ(storage::QuotaClientType::kAppcache, client_id);
-      EXPECT_EQ(StorageType::kTemporary, type);
-      ++notify_storage_modified_count_;
-      last_storage_key_ = storage_key;
-      last_delta_ = delta;
-      if (callback)
-        callback_task_runner->PostTask(FROM_HERE, std::move(callback));
-    }
-
-    // Not needed for our tests.
-    void RegisterClient(
-        mojo::PendingRemote<storage::mojom::QuotaClient> client,
-        storage::QuotaClientType quota_client_type,
-        const std::vector<blink::mojom::StorageType>& storage_types) override {}
-    void SetUsageCacheEnabled(storage::QuotaClientType client_id,
-                              const blink::StorageKey& storage_key,
-                              StorageType type,
-                              bool enabled) override {}
-    void GetUsageAndQuota(
-        const blink::StorageKey& storage_key,
-        blink::mojom::StorageType type,
-        scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
-        UsageAndQuotaCallback callback) override {
-      EXPECT_EQ(StorageType::kTemporary, type);
-      if (async_) {
-        callback_task_runner->PostTask(
-            FROM_HERE,
-            base::BindOnce(std::move(callback),
-                           blink::mojom::QuotaStatusCode::kOk, 0, kMockQuota));
-        return;
-      }
-      std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk, 0,
-                              kMockQuota);
-    }
-
-    int notify_storage_accessed_count_ = 0;
-    int notify_storage_modified_count_ = 0;
-    blink::StorageKey last_storage_key_;
-    int last_delta_ = 0;
-    bool async_ = false;
-
-   protected:
-    ~MockQuotaManagerProxy() override = default;
-  };
-
-  template <class Method>
-  void RunMethod(Method method) {
-    (this->*method)();
-  }
-
-  // Helper callback to run a test on our io_thread. The io_thread is spun up
-  // once and reused for all tests.
-  template <class Method>
-  void MethodWrapper(Method method) {
-    SetUpTest();
-
-    // Ensure InitTask execution prior to conducting a test.
-    FlushAllTasks();
-
-    // We also have to wait for InitTask completion call to be performed
-    // on the UI thread prior to running the test. Its guaranteed to be
-    // queued by this time.
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&AppCacheStorageImplTest::RunMethod<Method>,
-                                  base::Unretained(this), method));
-  }
-
-  static void SetUpTestCase() {
-    // We start the background thread as TYPE_IO because we also use the
-    // db_thread for the disk_cache which needs to be of TYPE_IO.
-    base::Thread::Options options(base::MessagePumpType::IO, 0);
-    background_thread =
-        std::make_unique<base::Thread>("AppCacheTest::BackgroundThread");
-    ASSERT_TRUE(background_thread->StartWithOptions(std::move(options)));
-  }
-
-  static void TearDownTestCase() {
-    background_thread.reset();
-  }
-
-  // Test harness --------------------------------------------------
-
-  AppCacheStorageImplTest()
-      : interceptor_(base::BindRepeating(&InterceptRequest)) {
-    ChildProcessSecurityPolicyImpl::GetInstance()->AddForTesting(
-        kProcessId, &browser_context_);
-    appcache_require_origin_trial_feature_.InitAndDisableFeature(
-        blink::features::kAppCacheRequireOriginTrial);
-  }
-
-  ~AppCacheStorageImplTest() override {
-    ChildProcessSecurityPolicyImpl::GetInstance()->Remove(kProcessId);
-  }
-
-  template <class Method>
-  void RunTestOnUIThread(Method method) {
-    base::RunLoop run_loop;
-    test_finished_cb_ = run_loop.QuitClosure();
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheStorageImplTest::MethodWrapper<Method>,
-                       base::Unretained(this), method));
-    run_loop.Run();
-  }
-
-  void SetUp() override {
-    // Calling GetDefaultStoragePartition kicks off a bunch of things,
-    // including setting up a disk cache, which checks feature lists.
-    // Defer until here so test constructors can set feature lists first.
-    weak_partition_factory_.emplace(static_cast<StoragePartitionImpl*>(
-        browser_context_.GetDefaultStoragePartition()));
-  }
-
-  void SetUpTest() {
-    service_ = std::make_unique<AppCacheServiceImpl>(nullptr, nullptr);
-    service_->set_appcache_policy(&mock_policy_);
-    service_->Initialize(base::FilePath());
-    mock_quota_manager_proxy_ = base::MakeRefCounted<MockQuotaManagerProxy>();
-    service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-  }
-
-  void TearDownTest() {
-    scoped_refptr<base::SequencedTaskRunner> db_runner =
-        storage()->db_task_runner_;
-    storage()->CancelDelegateCallbacks(delegate());
-    group_ = nullptr;
-    cache_ = nullptr;
-    cache2_ = nullptr;
-    mock_quota_manager_proxy_ = nullptr;
-    delegate_.reset();
-    service_.reset();
-    host_remote_.reset();
-    FlushTasks(db_runner.get());
-    FlushTasks(background_thread->task_runner().get());
-    FlushTasks(db_runner.get());
-  }
-
-  void TestFinished() {
-    // We unwind the stack prior to finishing up to let stack
-    // based objects get deleted.
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&AppCacheStorageImplTest::TestFinishedUnwound,
-                                  base::Unretained(this)));
-  }
-
-  void TestFinishedUnwound() {
-    TearDownTest();
-    std::move(test_finished_cb_).Run();
-  }
-
-  void PushNextTask(base::OnceClosure task) {
-    task_stack_.push(std::move(task));
-  }
-
-  void ScheduleNextTask() {
-    if (task_stack_.empty()) {
-      return;
-    }
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, std::move(task_stack_.top()));
-    task_stack_.pop();
-  }
-
-  static void SignalEvent(base::WaitableEvent* event) { event->Signal(); }
-
-  void FlushAllTasks() {
-    FlushTasks(storage()->db_task_runner_.get());
-    FlushTasks(background_thread->task_runner().get());
-    FlushTasks(storage()->db_task_runner_.get());
-  }
-
-  void FlushTasks(base::SequencedTaskRunner* runner) {
-    // We pump a task thru the db thread to ensure any tasks previously
-    // scheduled on that thread have been performed prior to return.
-    base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                              base::WaitableEvent::InitialState::NOT_SIGNALED);
-    runner->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheStorageImplTest::SignalEvent, &event));
-    event.Wait();
-  }
-
-  // LoadCache_Miss ----------------------------------------------------
-
-  void LoadCache_Miss() {
-    // Attempt to load a cache that doesn't exist. Should
-    // complete asynchronously.
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_LoadCache_Miss,
-                                base::Unretained(this)));
-
-    storage()->LoadCache(111, delegate());
-    EXPECT_NE(111, delegate()->loaded_cache_id_);
-  }
-
-  void Verify_LoadCache_Miss() {
-    EXPECT_EQ(111, delegate()->loaded_cache_id_);
-    EXPECT_FALSE(delegate()->loaded_cache_.get());
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    TestFinished();
-  }
-
-  // LoadCache_NearHit -------------------------------------------------
-
-  void LoadCache_NearHit() {
-    // Attempt to load a cache that is currently in use
-    // and does not require loading from storage. This
-    // load should complete syncly.
-
-    // Setup some preconditions. Make an 'unstored' cache for
-    // us to load. The ctor should put it in the working set.
-    int64_t cache_id = storage()->NewCacheId();
-    auto cache = base::MakeRefCounted<AppCache>(storage(), cache_id);
-    cache->set_manifest_parser_version(1);
-    cache->set_manifest_scope("/");
-
-    // Conduct the test.
-    storage()->LoadCache(cache_id, delegate());
-    EXPECT_EQ(cache_id, delegate()->loaded_cache_id_);
-    EXPECT_EQ(cache.get(), delegate()->loaded_cache_.get());
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    TestFinished();
-  }
-
-  void LoadCache_OriginTrialSuccess() {
-    AddToDatabase(kManifestUrl, 222, 111, valid_token_expires());
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 111;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 1;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    storage()->LoadCache(111, delegate());
-
-    PushNextTask(base::BindLambdaForTesting([&]() {
-      EXPECT_EQ(111, delegate()->loaded_cache_id_);
-      EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-      EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-      TestFinished();
-    }));
-  }
-
-  void LoadCache_OriginTrialFailure() {
-    int64_t cache_id = storage()->NewCacheId();
-    int64_t group_id = storage()->NewGroupId();
-    AddToDatabase(kManifestUrl, group_id, cache_id, invalid_token_expires());
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = cache_id;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 1;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    storage()->LoadCache(cache_id, delegate());
-    EXPECT_FALSE(delegate()->loaded_cache_.get());
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    TestFinished();
-  }
-
-  // CreateGroup  --------------------------------------------
-
-  void CreateGroupInEmptyOrigin() {
-    // Attempt to load a group that doesn't exist, one should
-    // be created for us, but not stored.
-
-    // Since the origin has no groups, the storage class will respond
-    // syncly.
-    storage()->LoadOrCreateGroup(kManifestUrl, delegate());
-    Verify_CreateGroup();
-  }
-
-  void CreateGroupInPopulatedOrigin() {
-    // Attempt to load a group that doesn't exist, one should
-    // be created for us, but not stored.
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_CreateGroup,
-                                base::Unretained(this)));
-
-    // Since the origin has groups, storage class will have to
-    // consult the database and completion will be async.
-    storage()->usage_map_[kOrigin] = kDefaultEntrySize;
-
-    storage()->LoadOrCreateGroup(kManifestUrl, delegate());
-    EXPECT_FALSE(delegate()->loaded_group_.get());
-  }
-
-  void Verify_CreateGroup() {
-    EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
-    EXPECT_TRUE(delegate()->loaded_group_.get());
-    EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
-    EXPECT_FALSE(delegate()->loaded_group_->newest_complete_cache());
-
-    // Should not have been stored in the database.
-    AppCacheDatabase::GroupRecord record;
-    EXPECT_FALSE(
-        database()->FindGroup(delegate()->loaded_group_->group_id(), &record));
-
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-
-    TestFinished();
-  }
-
-  // LoadGroupAndCache_FarHit  --------------------------------------
-
-  void LoadGroupAndCache_FarHit() {
-    // Attempt to load a cache that is not currently in use
-    // and does require loading from disk. This
-    // load should complete asynchronously.
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_LoadCache_Far_Hit,
-                       base::Unretained(this)));
-
-    // Setup some preconditions. Create a group and newest cache that
-    // appear to be "stored" and "not currently in use".
-    MakeCacheAndGroup(kManifestUrl, 1, 1, valid_token_expires(), true);
-    group_ = nullptr;
-    cache_ = nullptr;
-
-    // Conduct the cache load test, completes async
-    storage()->LoadCache(1, delegate());
-  }
-
-  void Verify_LoadCache_Far_Hit() {
-    EXPECT_TRUE(delegate()->loaded_cache_.get());
-    EXPECT_TRUE(delegate()->loaded_cache_->HasOneRef());
-    EXPECT_EQ(1, delegate()->loaded_cache_id_);
-
-    // The group should also have been loaded.
-    EXPECT_TRUE(delegate()->loaded_cache_->owning_group());
-    EXPECT_TRUE(delegate()->loaded_cache_->owning_group()->HasOneRef());
-    EXPECT_EQ(1, delegate()->loaded_cache_->owning_group()->group_id());
-
-    EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-
-    // Drop things from the working set.
-    delegate()->loaded_cache_ = nullptr;
-    EXPECT_FALSE(delegate()->loaded_group_.get());
-
-    // Conduct the group load test, also complete asynchronously.
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_LoadGroup_Far_Hit,
-                       base::Unretained(this)));
-
-    storage()->LoadOrCreateGroup(kManifestUrl, delegate());
-  }
-
-  void Verify_LoadGroup_Far_Hit() {
-    EXPECT_TRUE(delegate()->loaded_group_.get());
-    EXPECT_EQ(kManifestUrl, delegate()->loaded_manifest_url_);
-    EXPECT_TRUE(delegate()->loaded_group_->newest_complete_cache());
-    delegate()->loaded_groups_newest_cache_ = nullptr;
-    EXPECT_TRUE(delegate()->loaded_group_->HasOneRef());
-    EXPECT_EQ(2, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    TestFinished();
-  }
-
-  // StoreNewGroup  --------------------------------------
-
-  void StoreNewGroup() {
-    // Store a group and its newest cache. Should complete asynchronously.
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_StoreNewGroup,
-                                base::Unretained(this)));
-
-    // Setup some preconditions. Create a group and newest cache that
-    // appear to be "unstored".
-    group_ = base::MakeRefCounted<AppCacheGroup>(storage(), kManifestUrl,
-                                                 storage()->NewGroupId());
-    cache_ = base::MakeRefCounted<AppCache>(storage(), storage()->NewCacheId());
-    cache_->set_manifest_parser_version(1);
-    cache_->set_manifest_scope("/");
-    cache_->AddEntry(kEntryUrl,
-                     AppCacheEntry(AppCacheEntry::MASTER, 1, kDefaultEntrySize,
-                                   /*padding_size=*/0));
-    // Hold a ref to the cache simulate the UpdateJob holding that ref,
-    // and hold a ref to the group to simulate the CacheHost holding that ref.
-
-    // Have the quota manager return asynchronously for this test.
-    mock_quota_manager_proxy_->async_ = true;
-
-    // Conduct the store test.
-    storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
-  }
-
-  void Verify_StoreNewGroup() {
-    EXPECT_TRUE(delegate()->stored_group_success_);
-    EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
-    EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
-    EXPECT_TRUE(cache_->is_complete());
-
-    // Should have been stored in the database.
-    AppCacheDatabase::GroupRecord group_record;
-    AppCacheDatabase::CacheRecord cache_record;
-    EXPECT_TRUE(database()->FindGroup(group_->group_id(), &group_record));
-    EXPECT_TRUE(database()->FindCache(cache_->cache_id(), &cache_record));
-
-    // Verify quota bookkeeping
-    EXPECT_EQ(kDefaultEntrySize, storage()->usage_map_[kOrigin]);
-    EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    EXPECT_EQ(blink::StorageKey(kOrigin),
-              mock_quota_manager_proxy_->last_storage_key_);
-    EXPECT_EQ(kDefaultEntrySize, mock_quota_manager_proxy_->last_delta_);
-
-    TestFinished();
-  }
-
-  // StoreExistingGroup  --------------------------------------
-
-  void StoreExistingGroup() {
-    // Store a group and its newest cache. Should complete asynchronously.
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_StoreExistingGroup,
-                       base::Unretained(this)));
-
-    // Setup some preconditions. Create a group and old complete cache
-    // that appear to be "stored"
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    EXPECT_EQ(kDefaultEntrySize + kDefaultEntryPadding,
-              storage()->usage_map_[kOrigin]);
-
-    // And a newest unstored complete cache.
-    cache2_ = base::MakeRefCounted<AppCache>(storage(), 2);
-    cache2_->set_manifest_parser_version(1);
-    cache2_->set_manifest_scope("/");
-    cache2_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1,
-                                               kDefaultEntrySize + 100,
-                                               kDefaultEntryPadding + 1000));
-
-    // Conduct the test.
-    storage()->StoreGroupAndNewestCache(group_.get(), cache2_.get(),
-                                        delegate());
-    EXPECT_FALSE(delegate()->stored_group_success_);
-  }
-
-  void Verify_StoreExistingGroup() {
-    EXPECT_TRUE(delegate()->stored_group_success_);
-    EXPECT_EQ(group_.get(), delegate()->stored_group_.get());
-    EXPECT_EQ(cache2_.get(), group_->newest_complete_cache());
-    EXPECT_TRUE(cache2_->is_complete());
-
-    // The new cache should have been stored in the database.
-    AppCacheDatabase::GroupRecord group_record;
-    AppCacheDatabase::CacheRecord cache_record;
-    EXPECT_TRUE(database()->FindGroup(1, &group_record));
-    EXPECT_TRUE(database()->FindCache(2, &cache_record));
-
-    // The old cache should have been deleted
-    EXPECT_FALSE(database()->FindCache(1, &cache_record));
-
-    // Verify quota bookkeeping
-    EXPECT_EQ(kDefaultEntrySize + 100 + kDefaultEntryPadding + 1000,
-              storage()->usage_map_[kOrigin]);
-    EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    EXPECT_EQ(blink::StorageKey(kOrigin),
-              mock_quota_manager_proxy_->last_storage_key_);
-    EXPECT_EQ(100 + 1000, mock_quota_manager_proxy_->last_delta_);
-
-    TestFinished();
-  }
-
-  // StoreExistingGroupExistingCache  -------------------------------
-
-  void StoreExistingGroupExistingCache() {
-    // Store a group with updates to its existing newest complete cache.
-    // Setup some preconditions. Create a group and a complete cache that
-    // appear to be "stored".
-
-    // Setup some preconditions. Create a group and old complete cache
-    // that appear to be "stored"
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    EXPECT_EQ(kDefaultEntrySize + kDefaultEntryPadding,
-              storage()->usage_map_[kOrigin]);
-
-    // Change the cache.
-    base::Time now = base::Time::Now();
-    cache_->set_manifest_parser_version(1);
-    cache_->set_manifest_scope("/");
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                              /*response_id=*/1,
-                                              /*response_size=*/100,
-                                              /*padding_size=*/10));
-    cache_->set_update_time(now);
-
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_StoreExistingGroupExistingCache,
-        base::Unretained(this), now));
-
-    // Conduct the test.
-    EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
-    storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
-    EXPECT_FALSE(delegate()->stored_group_success_);
-  }
-
-  void Verify_StoreExistingGroupExistingCache(base::Time expected_update_time) {
-    EXPECT_TRUE(delegate()->stored_group_success_);
-    EXPECT_EQ(cache_.get(), group_->newest_complete_cache());
-
-    AppCacheDatabase::CacheRecord cache_record;
-    EXPECT_TRUE(database()->FindCache(1, &cache_record));
-    EXPECT_EQ(1, cache_record.cache_id);
-    EXPECT_EQ(1, cache_record.group_id);
-    EXPECT_FALSE(cache_record.online_wildcard);
-    EXPECT_TRUE(expected_update_time == cache_record.update_time);
-    EXPECT_EQ(100 + kDefaultEntrySize, cache_record.cache_size);
-    EXPECT_EQ(10 + kDefaultEntryPadding, cache_record.padding_size);
-
-    std::vector<AppCacheDatabase::EntryRecord> entry_records;
-    EXPECT_TRUE(database()->FindEntriesForCache(1, &entry_records));
-    EXPECT_EQ(2U, entry_records.size());
-    if (entry_records[0].url == kDefaultEntryUrl)
-      entry_records.erase(entry_records.begin());
-    EXPECT_EQ(1, entry_records[0].cache_id);
-    EXPECT_EQ(kEntryUrl, entry_records[0].url);
-    EXPECT_EQ(AppCacheEntry::EXPLICIT, entry_records[0].flags);
-    EXPECT_EQ(1, entry_records[0].response_id);
-    EXPECT_EQ(100, entry_records[0].response_size);
-    EXPECT_EQ(10, entry_records[0].padding_size);
-
-    // Verify quota bookkeeping
-    EXPECT_EQ(100 + 10 + kDefaultEntrySize + kDefaultEntryPadding,
-              storage()->usage_map_[kOrigin]);
-    EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    EXPECT_EQ(blink::StorageKey(kOrigin),
-              mock_quota_manager_proxy_->last_storage_key_);
-    EXPECT_EQ(100 + 10, mock_quota_manager_proxy_->last_delta_);
-
-    TestFinished();
-  }
-
-  // FailStoreGroup_SizeTooBig / FailStoreGroup_PaddingTooBig   ----------------
-
-  void FailStoreGroup_SizeTooBig() {
-    // Store a group and its newest cache. Should complete asynchronously.
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_FailStoreGroup,
-                                base::Unretained(this)));
-
-    // Set up some preconditions. Create a group and newest cache that
-    // appear to be "unstored" and big enough to exceed the 5M limit.
-    const int64_t kTooBig = 10 * 1024 * 1024;  // 10M
-    group_ = base::MakeRefCounted<AppCacheGroup>(storage(), kManifestUrl,
-                                                 storage()->NewGroupId());
-    cache_ = base::MakeRefCounted<AppCache>(storage(), storage()->NewCacheId());
-    cache_->set_manifest_parser_version(1);
-    cache_->set_manifest_scope("/");
-    cache_->AddEntry(kManifestUrl, AppCacheEntry(AppCacheEntry::MANIFEST,
-                                                 /*response_id=*/1,
-                                                 /*response_size=*/kTooBig,
-                                                 /*padding_size=*/0));
-    // Hold a ref to the cache to simulate the UpdateJob holding that ref,
-    // and hold a ref to the group to simulate the CacheHost holding that ref.
-
-    // Conduct the store test.
-    storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
-    EXPECT_FALSE(delegate()->stored_group_success_);  // Expected to be async.
-  }
-
-  void FailStoreGroup_PaddingTooBig() {
-    // Store a group and its newest cache. Should complete asynchronously.
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_FailStoreGroup,
-                                base::Unretained(this)));
-
-    // Set up some preconditions. Create a group and newest cache that
-    // appear to be "unstored" and big enough to exceed the 5M limit.
-    const int64_t kTooBig = 10 * 1024 * 1024;  // 10M
-    group_ = base::MakeRefCounted<AppCacheGroup>(storage(), kManifestUrl,
-                                                 storage()->NewGroupId());
-    cache_ = base::MakeRefCounted<AppCache>(storage(), storage()->NewCacheId());
-    cache_->set_manifest_parser_version(1);
-    cache_->set_manifest_scope("/");
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                              /*response_id=*/1,
-                                              /*response_size=*/1,
-                                              /*padding_size=*/kTooBig));
-    // Hold a ref to the cache to simulate the UpdateJob holding that ref,
-    // and hold a ref to the group to simulate the CacheHost holding that ref.
-
-    // Conduct the store test.
-    storage()->StoreGroupAndNewestCache(group_.get(), cache_.get(), delegate());
-    EXPECT_FALSE(delegate()->stored_group_success_);  // Expected to be async.
-  }
-
-  void Verify_FailStoreGroup() {
-    EXPECT_FALSE(delegate()->stored_group_success_);
-    EXPECT_TRUE(delegate()->would_exceed_quota_);
-
-    // Should not have been stored in the database.
-    AppCacheDatabase::GroupRecord group_record;
-    AppCacheDatabase::CacheRecord cache_record;
-    EXPECT_FALSE(database()->FindGroup(group_->group_id(), &group_record));
-    EXPECT_FALSE(database()->FindCache(cache_->cache_id(), &cache_record));
-
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_accessed_count_);
-    EXPECT_EQ(0, mock_quota_manager_proxy_->notify_storage_modified_count_);
-
-    TestFinished();
-  }
-
-  // MakeGroupObsolete  -------------------------------
-
-  void MakeGroupObsolete() {
-    // Make a group obsolete, should complete asynchronously.
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_MakeGroupObsolete,
-                       base::Unretained(this)));
-
-    // Setup some preconditions. Create a group and newest cache that
-    // appears to be "stored" and "currently in use".
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    EXPECT_EQ(kDefaultEntrySize + kDefaultEntryPadding,
-              storage()->usage_map_[kOrigin]);
-
-    // Also insert some related records.
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.flags = AppCacheEntry::FALLBACK;
-    entry_record.response_id = 1;
-    entry_record.url = kEntryUrl;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    AppCacheDatabase::NamespaceRecord fallback_namespace_record;
-    fallback_namespace_record.cache_id = 1;
-    fallback_namespace_record.namespace_.target_url = kEntryUrl;
-    fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
-    fallback_namespace_record.origin = url::Origin::Create(kManifestUrl);
-    EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
-
-    AppCacheDatabase::OnlineSafeListRecord online_safelist_record;
-    online_safelist_record.cache_id = 1;
-    online_safelist_record.namespace_url = kOnlineNamespace;
-    EXPECT_TRUE(database()->InsertOnlineSafeList(&online_safelist_record));
-
-    // Conduct the test.
-    storage()->MakeGroupObsolete(group_.get(), delegate(), 0);
-    EXPECT_FALSE(group_->is_obsolete());
-  }
-
-  void Verify_MakeGroupObsolete() {
-    EXPECT_TRUE(delegate()->obsoleted_success_);
-    EXPECT_EQ(group_.get(), delegate()->obsoleted_group_.get());
-    EXPECT_TRUE(group_->is_obsolete());
-    EXPECT_TRUE(storage()->usage_map_.empty());
-
-    // The cache and group have been deleted from the database.
-    AppCacheDatabase::GroupRecord group_record;
-    AppCacheDatabase::CacheRecord cache_record;
-    EXPECT_FALSE(database()->FindGroup(1, &group_record));
-    EXPECT_FALSE(database()->FindCache(1, &cache_record));
-
-    // The related records should have been deleted too.
-    std::vector<AppCacheDatabase::EntryRecord> entry_records;
-    database()->FindEntriesForCache(1, &entry_records);
-    EXPECT_TRUE(entry_records.empty());
-    std::vector<AppCacheDatabase::NamespaceRecord> intercept_records;
-    std::vector<AppCacheDatabase::NamespaceRecord> fallback_records;
-    database()->FindNamespacesForCache(1, &intercept_records,
-                                       &fallback_records);
-    EXPECT_TRUE(fallback_records.empty());
-    std::vector<AppCacheDatabase::OnlineSafeListRecord> safelist_records;
-    database()->FindOnlineSafeListForCache(1, &safelist_records);
-    EXPECT_TRUE(safelist_records.empty());
-
-    // Verify quota bookkeeping
-    EXPECT_TRUE(storage()->usage_map_.empty());
-    EXPECT_EQ(1, mock_quota_manager_proxy_->notify_storage_modified_count_);
-    EXPECT_EQ(blink::StorageKey(kOrigin),
-              mock_quota_manager_proxy_->last_storage_key_);
-    EXPECT_EQ(-(kDefaultEntrySize + kDefaultEntryPadding),
-              mock_quota_manager_proxy_->last_delta_);
-
-    TestFinished();
-  }
-
-  // MarkEntryAsForeign  -------------------------------
-
-  void MarkEntryAsForeign() {
-    // Setup some preconditions. Create a cache with an entry
-    // in storage and in the working set.
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 0;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
-
-    // Conduct the test.
-    storage()->MarkEntryAsForeign(kEntryUrl, 1);
-
-    // The entry in the working set should have been updated syncly.
-    EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsForeign());
-    EXPECT_TRUE(cache_->GetEntry(kEntryUrl)->IsExplicit());
-
-    // And the entry in storage should also be updated, but that
-    // happens asynchronously on the db thread.
-    FlushAllTasks();
-    AppCacheDatabase::EntryRecord entry_record2;
-    EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record2));
-    EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
-              entry_record2.flags);
-    TestFinished();
-  }
-
-  // MarkEntryAsForeignWithLoadInProgress  -------------------------------
-
-  void MarkEntryAsForeignWithLoadInProgress() {
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_MarkEntryAsForeignWithLoadInProgress,
-        base::Unretained(this)));
-
-    // Setup some preconditions. Create a cache with an entry
-    // in storage, but not in the working set.
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT));
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 0;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    EXPECT_FALSE(cache_->GetEntry(kEntryUrl)->IsForeign());
-    EXPECT_TRUE(cache_->HasOneRef());
-    cache_ = nullptr;
-    group_ = nullptr;
-
-    // Conduct the test, start a cache load, and prior to completion
-    // of that load, mark the entry as foreign.
-    storage()->LoadCache(1, delegate());
-    storage()->MarkEntryAsForeign(kEntryUrl, 1);
-  }
-
-  void Verify_MarkEntryAsForeignWithLoadInProgress() {
-    EXPECT_EQ(1, delegate()->loaded_cache_id_);
-    EXPECT_TRUE(delegate()->loaded_cache_.get());
-
-    // The entry in the working set should have been updated upon load.
-    EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsForeign());
-    EXPECT_TRUE(delegate()->loaded_cache_->GetEntry(kEntryUrl)->IsExplicit());
-
-    // And the entry in storage should also be updated.
-    FlushAllTasks();
-    AppCacheDatabase::EntryRecord entry_record;
-    EXPECT_TRUE(database()->FindEntry(1, kEntryUrl, &entry_record));
-    EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
-              entry_record.flags);
-    TestFinished();
-  }
-
-  // FindNoMainResponse  -------------------------------
-
-  void FindNoMainResponse() {
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
-                       base::Unretained(this)));
-
-    // Conduct the test.
-    storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void Verify_FindNoMainResponse() {
-    EXPECT_EQ(kEntryUrl, delegate()->found_url_);
-    EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, delegate()->found_cache_id_);
-    EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-              delegate()->found_entry_.response_id());
-    EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-              delegate()->found_fallback_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
-    EXPECT_EQ(0, delegate()->found_entry_.types());
-    EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
-    TestFinished();
-  }
-
-  // BasicFindMainResponse  -------------------------------
-
-  void BasicFindMainResponseInDatabase() { BasicFindMainResponse(true); }
-
-  void BasicFindMainResponseInWorkingSet() { BasicFindMainResponse(false); }
-
-  void BasicFindMainResponse(bool drop_from_working_set) {
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_BasicFindMainResponse,
-                       base::Unretained(this)));
-
-    // Setup some preconditions. Create a complete cache with an entry
-    // in storage.
-    MakeCacheAndGroup(kManifestUrl, 2, 1, invalid_token_expires(), true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, 1));
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 1;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    // Optionally drop the cache/group pair from the working set.
-    if (drop_from_working_set) {
-      EXPECT_TRUE(cache_->HasOneRef());
-      cache_ = nullptr;
-      EXPECT_TRUE(group_->HasOneRef());
-      group_ = nullptr;
-    }
-
-    // Conduct the test.
-    storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void BasicFindMainResponse_OriginTrialFailure() {
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_FindNoMainResponse,
-                       base::Unretained(this)));
-
-    // Add cache/group/entry to the database.
-    AddToDatabase(kManifestUrl, 2, 1, invalid_token_expires());
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = 1;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    // Conduct the test.
-    storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void Verify_BasicFindMainResponse() {
-    EXPECT_EQ(kEntryUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
-    EXPECT_EQ(1, delegate()->found_cache_id_);
-    EXPECT_EQ(2, delegate()->found_group_id_);
-    EXPECT_EQ(1, delegate()->found_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
-    EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
-    TestFinished();
-  }
-
-  // BasicFindMainFallbackResponse  -------------------------------
-
-  void BasicFindMainFallbackResponseInDatabase() {
-    BasicFindMainFallbackResponse(true);
-  }
-
-  void BasicFindMainFallbackResponseInWorkingSet() {
-    BasicFindMainFallbackResponse(false);
-  }
-
-  void BasicFindMainFallbackResponse(bool drop_from_working_set) {
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_BasicFindMainFallbackResponse,
-        base::Unretained(this)));
-
-    // Setup some preconditions. Create a complete cache with a
-    // fallback namespace and entry.
-    MakeCacheAndGroup(kManifestUrl, 2, 1, valid_token_expires(), true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
-    cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace2, kEntryUrl2);
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace, kEntryUrl);
-    AppCacheDatabase::CacheRecord cache_record;
-    std::vector<AppCacheDatabase::EntryRecord> entries;
-    std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
-    std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
-    std::vector<AppCacheDatabase::OnlineSafeListRecord> safelists;
-    cache_->ToDatabaseRecords(group_.get(), &cache_record, &entries,
-                              &intercepts, &fallbacks, &safelists);
-
-    for (const auto& entry : entries) {
-      // MakeCacheAndGroup has inserted the default entry record already.
-      if (entry.url != kDefaultEntryUrl)
-        EXPECT_TRUE(database()->InsertEntry(&entry));
-    }
-
-    EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
-    EXPECT_TRUE(database()->InsertOnlineSafeListRecords(safelists));
-    if (drop_from_working_set) {
-      EXPECT_TRUE(cache_->HasOneRef());
-      cache_ = nullptr;
-      EXPECT_TRUE(group_->HasOneRef());
-      group_ = nullptr;
-    }
-
-    // Conduct the test. The test url is in both fallback namespace urls,
-    // but should match the longer of the two.
-    storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
-    EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
-  }
-
-  void Verify_BasicFindMainFallbackResponse() {
-    EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
-    EXPECT_EQ(1, delegate()->found_cache_id_);
-    EXPECT_EQ(2, delegate()->found_group_id_);
-    EXPECT_FALSE(delegate()->found_entry_.has_response_id());
-    EXPECT_EQ(2, delegate()->found_fallback_entry_.response_id());
-    EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
-    EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
-    TestFinished();
-  }
-
-  void FindMainFallbackResponse_OriginTrialFailure() {
-    PushNextTask(base::BindLambdaForTesting([&]() {
-      EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
-      EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
-      EXPECT_EQ(0, delegate()->found_cache_id_);
-      EXPECT_EQ(0, delegate()->found_group_id_);
-      EXPECT_FALSE(delegate()->found_entry_.has_response_id());
-      EXPECT_EQ(0, delegate()->found_fallback_entry_.response_id());
-      EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
-      TestFinished();
-    }));
-
-    // Setup some preconditions. Create a complete cache with a
-    // fallback namespace and entry.
-    MakeCacheAndGroup(kManifestUrl, 2, 1, invalid_token_expires(), true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::FALLBACK, 1));
-    cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace2, kEntryUrl2);
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace, kEntryUrl);
-    AppCacheDatabase::CacheRecord cache_record;
-    std::vector<AppCacheDatabase::EntryRecord> entries;
-    std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
-    std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
-    std::vector<AppCacheDatabase::OnlineSafeListRecord> safelists;
-    cache_->ToDatabaseRecords(group_.get(), &cache_record, &entries,
-                              &intercepts, &fallbacks, &safelists);
-
-    for (const auto& entry : entries) {
-      // MakeCacheAndGroup has inserted the default entry record already.
-      if (entry.url != kDefaultEntryUrl)
-        EXPECT_TRUE(database()->InsertEntry(&entry));
-    }
-
-    cache_ = nullptr;
-    group_ = nullptr;
-
-    EXPECT_TRUE(database()->InsertNamespaceRecords(fallbacks));
-    EXPECT_TRUE(database()->InsertOnlineSafeListRecords(safelists));
-
-    // Conduct the test. Although the test url is in both fallback namespace
-    // urls, it will match neither of them because its group does not have a
-    // valid origin trial token.
-    storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
-    EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
-  }
-
-  // BasicFindMainInterceptResponse  -------------------------------
-
-  void BasicFindMainInterceptResponseInDatabase() {
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_BasicFindMainInterceptResponse,
-        base::Unretained(this)));
-    BasicFindMainInterceptResponse(true, valid_token_expires());
-  }
-
-  void BasicFindMainInterceptResponseInWorkingSet() {
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_BasicFindMainInterceptResponse,
-        base::Unretained(this)));
-    BasicFindMainInterceptResponse(false, valid_token_expires());
-  }
-
-  void FindMainInterceptResponse_OriginTrialFailure() {
-    PushNextTask(base::BindLambdaForTesting([&]() {
-      EXPECT_EQ(kInterceptTestUrl, delegate()->found_url_);
-      EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
-      EXPECT_EQ(0, delegate()->found_cache_id_);
-      EXPECT_EQ(0, delegate()->found_group_id_);
-      EXPECT_FALSE(delegate()->found_entry_.has_response_id());
-      EXPECT_EQ(0, delegate()->found_fallback_entry_.response_id());
-      EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
-      TestFinished();
-    }));
-    BasicFindMainInterceptResponse(true, invalid_token_expires());
-  }
-
-  void BasicFindMainInterceptResponse(bool drop_from_working_set,
-                                      base::Time token_expires) {
-    // Setup some preconditions. Create a complete cache with an
-    // intercept namespace and entry.
-    MakeCacheAndGroup(kManifestUrl, 2, 1, token_expires, true);
-    cache_->AddEntry(kEntryUrl, AppCacheEntry(AppCacheEntry::INTERCEPT, 1));
-    cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::INTERCEPT, 2));
-    cache_->intercept_namespaces_.emplace_back(
-        APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace2, kEntryUrl2);
-    cache_->intercept_namespaces_.emplace_back(APPCACHE_INTERCEPT_NAMESPACE,
-                                               kInterceptNamespace, kEntryUrl);
-    AppCacheDatabase::CacheRecord cache_record;
-    std::vector<AppCacheDatabase::EntryRecord> entries;
-    std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
-    std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
-    std::vector<AppCacheDatabase::OnlineSafeListRecord> safelists;
-    cache_->ToDatabaseRecords(group_.get(), &cache_record, &entries,
-                              &intercepts, &fallbacks, &safelists);
-
-    for (const auto& entry : entries) {
-      // MakeCacheAndGroup has inserted  the default entry record already
-      if (entry.url != kDefaultEntryUrl)
-        EXPECT_TRUE(database()->InsertEntry(&entry));
-    }
-
-    EXPECT_TRUE(database()->InsertNamespaceRecords(intercepts));
-    EXPECT_TRUE(database()->InsertOnlineSafeListRecords(safelists));
-    if (drop_from_working_set) {
-      EXPECT_TRUE(cache_->HasOneRef());
-      cache_ = nullptr;
-      EXPECT_TRUE(group_->HasOneRef());
-      group_ = nullptr;
-    }
-
-    // Conduct the test. The test url is in both intercept namespaces,
-    // but should match the longer of the two.
-    storage()->FindResponseForMainRequest(kInterceptTestUrl, GURL(),
-                                          delegate());
-    EXPECT_NE(kInterceptTestUrl, delegate()->found_url_);
-  }
-
-  void Verify_BasicFindMainInterceptResponse() {
-    EXPECT_EQ(kInterceptTestUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
-    EXPECT_EQ(1, delegate()->found_cache_id_);
-    EXPECT_EQ(2, delegate()->found_group_id_);
-    EXPECT_EQ(2, delegate()->found_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_entry_.IsIntercept());
-    EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
-    EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
-    TestFinished();
-  }
-
-  // FindMainResponseWithMultipleHits  -------------------------------
-
-  void FindMainResponseWithMultipleHits() {
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits,
-        base::Unretained(this)));
-
-    // Setup some preconditions, create a few caches with an identical set
-    // of entries and fallback namespaces. Only the last one remains in
-    // the working set to simulate appearing as "in use".
-    MakeMultipleHitCacheAndGroup(kManifestUrl, 1);
-    MakeMultipleHitCacheAndGroup(kManifestUrl2, 2);
-    MakeMultipleHitCacheAndGroup(kManifestUrl3, 3);
-
-    // Conduct the test, we should find the response from the last cache
-    // since it's "in use".
-    storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void MakeMultipleHitCacheAndGroup(const GURL& manifest_url, int id) {
-    MakeCacheAndGroup(manifest_url, id, id, invalid_token_expires(), true);
-    AppCacheDatabase::EntryRecord entry_record;
-
-    // Add an entry for kEntryUrl
-    entry_record.cache_id = id;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT;
-    entry_record.response_id = id;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    cache_->AddEntry(entry_record.url, AppCacheEntry(entry_record.flags,
-                                                     entry_record.response_id));
-
-    // Add an entry for the manifestUrl
-    entry_record.cache_id = id;
-    entry_record.url = manifest_url;
-    entry_record.flags = AppCacheEntry::MANIFEST;
-    entry_record.response_id = id + kManifestEntryIdOffset;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    cache_->AddEntry(entry_record.url, AppCacheEntry(entry_record.flags,
-                                                     entry_record.response_id));
-
-    // Add a fallback entry and namespace
-    entry_record.cache_id = id;
-    entry_record.url = kEntryUrl2;
-    entry_record.flags = AppCacheEntry::FALLBACK;
-    entry_record.response_id = id + kFallbackEntryIdOffset;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    cache_->AddEntry(entry_record.url, AppCacheEntry(entry_record.flags,
-                                                     entry_record.response_id));
-    AppCacheDatabase::NamespaceRecord fallback_namespace_record;
-    fallback_namespace_record.cache_id = id;
-    fallback_namespace_record.namespace_.target_url = entry_record.url;
-    fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
-    fallback_namespace_record.origin = url::Origin::Create(manifest_url);
-    EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace, kEntryUrl2);
-  }
-
-  void Verify_FindMainResponseWithMultipleHits() {
-    EXPECT_EQ(kEntryUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
-    EXPECT_EQ(3, delegate()->found_cache_id_);
-    EXPECT_EQ(3, delegate()->found_group_id_);
-    EXPECT_EQ(3, delegate()->found_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
-    EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
-
-    // Conduct another test preferring kManifestUrl
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits2,
-        base::Unretained(this)));
-    storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl, delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void Verify_FindMainResponseWithMultipleHits2() {
-    EXPECT_EQ(kEntryUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl, delegate()->found_manifest_url_);
-    EXPECT_EQ(1, delegate()->found_cache_id_);
-    EXPECT_EQ(1, delegate()->found_group_id_);
-    EXPECT_EQ(1, delegate()->found_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
-    EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
-
-    // Conduct the another test preferring kManifestUrl2
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits3,
-        base::Unretained(this)));
-    storage()->FindResponseForMainRequest(kEntryUrl, kManifestUrl2, delegate());
-    EXPECT_NE(kEntryUrl, delegate()->found_url_);
-  }
-
-  void Verify_FindMainResponseWithMultipleHits3() {
-    EXPECT_EQ(kEntryUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
-    EXPECT_EQ(2, delegate()->found_cache_id_);
-    EXPECT_EQ(2, delegate()->found_group_id_);
-    EXPECT_EQ(2, delegate()->found_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_entry_.IsExplicit());
-    EXPECT_FALSE(delegate()->found_fallback_entry_.has_response_id());
-
-    // Conduct another test with no preferred manifest that hits the fallback.
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits4,
-        base::Unretained(this)));
-    storage()->FindResponseForMainRequest(kFallbackTestUrl, GURL(), delegate());
-    EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
-  }
-
-  void Verify_FindMainResponseWithMultipleHits4() {
-    EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl3, delegate()->found_manifest_url_);
-    EXPECT_EQ(3, delegate()->found_cache_id_);
-    EXPECT_EQ(3, delegate()->found_group_id_);
-    EXPECT_FALSE(delegate()->found_entry_.has_response_id());
-    EXPECT_EQ(3 + kFallbackEntryIdOffset,
-              delegate()->found_fallback_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
-    EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
-
-    // Conduct another test preferring kManifestUrl2 that hits the fallback.
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-    PushNextTask(base::BindOnce(
-        &AppCacheStorageImplTest::Verify_FindMainResponseWithMultipleHits5,
-        base::Unretained(this)));
-    storage()->FindResponseForMainRequest(kFallbackTestUrl, kManifestUrl2,
-                                          delegate());
-    EXPECT_NE(kFallbackTestUrl, delegate()->found_url_);
-  }
-
-  void Verify_FindMainResponseWithMultipleHits5() {
-    EXPECT_EQ(kFallbackTestUrl, delegate()->found_url_);
-    EXPECT_EQ(kManifestUrl2, delegate()->found_manifest_url_);
-    EXPECT_EQ(2, delegate()->found_cache_id_);
-    EXPECT_EQ(2, delegate()->found_group_id_);
-    EXPECT_FALSE(delegate()->found_entry_.has_response_id());
-    EXPECT_EQ(2 + kFallbackEntryIdOffset,
-              delegate()->found_fallback_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_fallback_entry_.IsFallback());
-    EXPECT_EQ(kEntryUrl2, delegate()->found_namespace_entry_url_);
-
-    TestFinished();
-  }
-
-  // FindMainResponseExclusions  -------------------------------
-
-  void FindMainResponseExclusionsInDatabase() {
-    FindMainResponseExclusions(true);
-  }
-
-  void FindMainResponseExclusionsInWorkingSet() {
-    FindMainResponseExclusions(false);
-  }
-
-  void FindMainResponseExclusions(bool drop_from_working_set) {
-    // Setup some preconditions. Create a complete cache with a
-    // foreign entry, an online namespace, and a second online
-    // namespace nested within a fallback namespace.
-    MakeCacheAndGroup(kManifestUrl, 1, 1, invalid_token_expires(), true);
-    cache_->AddEntry(
-        kEntryUrl,
-        AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN, 1));
-    cache_->AddEntry(kEntryUrl2, AppCacheEntry(AppCacheEntry::FALLBACK, 2));
-    cache_->fallback_namespaces_.emplace_back(APPCACHE_FALLBACK_NAMESPACE,
-                                              kFallbackNamespace, kEntryUrl2);
-    cache_->online_safelist_namespaces_.emplace_back(APPCACHE_NETWORK_NAMESPACE,
-                                                     kOnlineNamespace, GURL());
-    cache_->online_safelist_namespaces_.emplace_back(
-        APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceWithinFallback, GURL());
-
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = 1;
-    entry_record.url = kEntryUrl;
-    entry_record.flags = AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN;
-    entry_record.response_id = 1;
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-    AppCacheDatabase::OnlineSafeListRecord safelist_record;
-    safelist_record.cache_id = 1;
-    safelist_record.namespace_url = kOnlineNamespace;
-    EXPECT_TRUE(database()->InsertOnlineSafeList(&safelist_record));
-    AppCacheDatabase::NamespaceRecord fallback_namespace_record;
-    fallback_namespace_record.cache_id = 1;
-    fallback_namespace_record.namespace_.target_url = kEntryUrl2;
-    fallback_namespace_record.namespace_.namespace_url = kFallbackNamespace;
-    fallback_namespace_record.origin = url::Origin::Create(kManifestUrl);
-    EXPECT_TRUE(database()->InsertNamespace(&fallback_namespace_record));
-    safelist_record.cache_id = 1;
-    safelist_record.namespace_url = kOnlineNamespaceWithinFallback;
-    EXPECT_TRUE(database()->InsertOnlineSafeList(&safelist_record));
-    if (drop_from_working_set) {
-      cache_ = nullptr;
-      group_ = nullptr;
-    }
-
-    // We should not find anything for the foreign entry.
-    PushNextTask(
-        base::BindOnce(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
-                       base::Unretained(this), kEntryUrl, 1));
-    storage()->FindResponseForMainRequest(kEntryUrl, GURL(), delegate());
-  }
-
-  void Verify_ExclusionNotFound(GURL expected_url, int phase) {
-    EXPECT_EQ(expected_url, delegate()->found_url_);
-    EXPECT_TRUE(delegate()->found_manifest_url_.is_empty());
-    EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, delegate()->found_cache_id_);
-    EXPECT_EQ(0, delegate()->found_group_id_);
-    EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-              delegate()->found_entry_.response_id());
-    EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-              delegate()->found_fallback_entry_.response_id());
-    EXPECT_TRUE(delegate()->found_namespace_entry_url_.is_empty());
-    EXPECT_EQ(0, delegate()->found_entry_.types());
-    EXPECT_EQ(0, delegate()->found_fallback_entry_.types());
-
-    if (phase == 1) {
-      // We should not find anything for the online namespace.
-      PushNextTask(
-          base::BindOnce(&AppCacheStorageImplTest::Verify_ExclusionNotFound,
-                         base::Unretained(this), kOnlineNamespace, 2));
-      storage()->FindResponseForMainRequest(kOnlineNamespace, GURL(),
-                                            delegate());
-      return;
-    }
-    if (phase == 2) {
-      // We should not find anything for the online namespace nested within
-      // the fallback namespace.
-      PushNextTask(base::BindOnce(
-          &AppCacheStorageImplTest::Verify_ExclusionNotFound,
-          base::Unretained(this), kOnlineNamespaceWithinFallback, 3));
-      storage()->FindResponseForMainRequest(kOnlineNamespaceWithinFallback,
-                                            GURL(), delegate());
-      return;
-    }
-
-    TestFinished();
-  }
-
-  // Reinitialize -------------------------------
-  // These tests are somewhat of a system integration test.
-  // They rely on running a mock http server on our IO thread,
-  // and involves other appcache classes to get some code
-  // coverage thruout when Reinitialize happens.
-
-  class MockServiceObserver : public AppCacheServiceImpl::Observer {
-   public:
-    explicit MockServiceObserver(AppCacheStorageImplTest* test) : test_(test) {}
-
-    void OnServiceReinitialized(
-        AppCacheStorageReference* old_storage_ref) override {
-      observed_old_storage_ = old_storage_ref;
-      test_->ScheduleNextTask();
-    }
-
-    scoped_refptr<AppCacheStorageReference> observed_old_storage_;
-    AppCacheStorageImplTest* test_;
-  };
-
-  class MockAppCacheFrontend : public blink::mojom::AppCacheFrontend {
-   public:
-    MockAppCacheFrontend() = default;
-
-    void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {}
-    void EventRaised(blink::mojom::AppCacheEventID event_id) override {}
-    void ProgressEventRaised(const GURL& url,
-                             int32_t num_total,
-                             int32_t num_complete) override {}
-    void ErrorEventRaised(
-        blink::mojom::AppCacheErrorDetailsPtr details) override {
-      error_event_was_raised_ = true;
-    }
-    void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
-                    const std::string& message) override {}
-    void SetSubresourceFactory(
-        mojo::PendingRemote<network::mojom::URLLoaderFactory>
-            url_loader_factory) override {}
-
-    bool error_event_was_raised_ = false;
-  };
-
-  enum ReinitTestCase {
-    CORRUPT_CACHE_ON_INSTALL,
-    CORRUPT_CACHE_ON_LOAD_EXISTING,
-    CORRUPT_SQL_ON_INSTALL
-  };
-
-  void Reinitialize1() {
-    // Recover from a corrupt disk cache discovered while
-    // installing a new appcache.
-    Reinitialize(CORRUPT_CACHE_ON_INSTALL);
-  }
-
-  void Reinitialize2() {
-    // Recover from a corrupt disk cache discovered while
-    // trying to load a resource from an existing appcache.
-    Reinitialize(CORRUPT_CACHE_ON_LOAD_EXISTING);
-  }
-
-  void Reinitialize3() {
-    // Recover from a corrupt sql database discovered while
-    // installing a new appcache.
-    Reinitialize(CORRUPT_SQL_ON_INSTALL);
-  }
-
-  void Reinitialize(ReinitTestCase test_case) {
-    // Unlike all of the other tests, this one actually read/write files.
-    ASSERT_TRUE(temp_directory_.CreateUniqueTempDir());
-
-    AppCacheDatabase db(temp_directory_.GetPath().AppendASCII("Index"));
-    EXPECT_TRUE(db.LazyOpen(true));
-
-    if (test_case == CORRUPT_CACHE_ON_INSTALL ||
-        test_case == CORRUPT_CACHE_ON_LOAD_EXISTING) {
-      // Create a corrupt/unopenable disk_cache index file.
-      const std::string kCorruptData("deadbeef");
-      base::FilePath disk_cache_directory =
-          temp_directory_.GetPath().AppendASCII("Cache");
-      ASSERT_TRUE(base::CreateDirectory(disk_cache_directory));
-      base::FilePath index_file = disk_cache_directory.AppendASCII("index");
-      EXPECT_TRUE(base::WriteFile(index_file, kCorruptData));
-
-      // Also add a corrupt entry file so that simple disk_cache does not try
-      // to automatically recover from the corrupted index.
-      base::FilePath entry_file =
-          disk_cache_directory.AppendASCII("01234567_0");
-      EXPECT_TRUE(base::WriteFile(entry_file, kCorruptData));
-    }
-
-    // Create records for a degenerate cached manifest that only contains
-    // one entry for the manifest file resource.
-    if (test_case == CORRUPT_CACHE_ON_LOAD_EXISTING) {
-      GURL manifest_url = GetMockUrl("manifest");
-
-      AppCacheDatabase::GroupRecord group_record;
-      group_record.group_id = 1;
-      group_record.manifest_url = manifest_url;
-      group_record.origin = url::Origin::Create(manifest_url);
-      EXPECT_TRUE(db.InsertGroup(&group_record));
-      AppCacheDatabase::CacheRecord cache_record;
-      cache_record.cache_id = 1;
-      cache_record.group_id = 1;
-      cache_record.online_wildcard = false;
-      cache_record.update_time = kZeroTime;
-      cache_record.cache_size = kDefaultEntrySize;
-      cache_record.padding_size = 0;
-      cache_record.manifest_parser_version = 1;
-      cache_record.manifest_scope = std::string("/");
-      EXPECT_TRUE(db.InsertCache(&cache_record));
-      AppCacheDatabase::EntryRecord entry_record;
-      entry_record.cache_id = 1;
-      entry_record.url = manifest_url;
-      entry_record.flags = AppCacheEntry::MANIFEST;
-      entry_record.response_id = 1;
-      entry_record.response_size = kDefaultEntrySize;
-      entry_record.padding_size = 0;
-      EXPECT_TRUE(db.InsertEntry(&entry_record));
-    }
-
-    // Recreate the service to point at the db and corruption on disk.
-    service_ = std::make_unique<AppCacheServiceImpl>(
-        nullptr, weak_partition_factory_->GetWeakPtr());
-
-    service_->set_appcache_policy(&mock_policy_);
-    service_->Initialize(temp_directory_.GetPath());
-    mock_quota_manager_proxy_ = base::MakeRefCounted<MockQuotaManagerProxy>();
-    service_->quota_manager_proxy_ = mock_quota_manager_proxy_;
-    delegate_ = std::make_unique<MockStorageDelegate>(this);
-
-    // Additional setup to observe reinitailize happens.
-    observer_ = std::make_unique<MockServiceObserver>(this);
-    service_->AddObserver(observer_.get());
-
-    // We continue after the init task is complete including the callback
-    // on the current thread.
-    FlushAllTasks();
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheStorageImplTest::Continue_Reinitialize,
-                       base::Unretained(this), test_case));
-  }
-
-  void Continue_Reinitialize(ReinitTestCase test_case) {
-    const int kMockRenderFrameId = MSG_ROUTING_NONE;
-    if (test_case == CORRUPT_SQL_ON_INSTALL) {
-      // Break the db file
-      EXPECT_FALSE(database()->was_corruption_detected());
-      ASSERT_TRUE(sql::test::CorruptSizeInHeader(
-          temp_directory_.GetPath().AppendASCII("Index")));
-    }
-
-    if (test_case == CORRUPT_CACHE_ON_INSTALL ||
-        test_case == CORRUPT_SQL_ON_INSTALL) {
-      // Try to create a new appcache, the resulting update job will
-      // eventually fail when it gets to disk cache initialization.
-      host1_id_ = base::UnguessableToken::Create();
-      service_->RegisterHost(
-          host_remote_.BindNewPipeAndPassReceiver(), BindFrontend(), host1_id_,
-          kMockRenderFrameId, kMockProcessId,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId),
-          GetBadMessageCallback());
-      AppCacheHost* host1 = service_->GetHost(host1_id_);
-      const GURL kEmptyPageUrl(GetMockUrl("empty.html"));
-      host1->SetSiteForCookiesForTesting(
-          net::SiteForCookies::FromUrl(kEmptyPageUrl));
-      host1->SelectCache(kEmptyPageUrl, blink::mojom::kAppCacheNoCacheId,
-                         GetMockUrl("manifest"));
-    } else {
-      ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
-      // Try to access the existing cache manifest.
-      // The URLRequestJob  will eventually fail when it gets to disk
-      // cache initialization.
-      host2_id_ = base::UnguessableToken::Create();
-      service_->RegisterHost(
-          host_remote_.BindNewPipeAndPassReceiver(), BindFrontend(), host2_id_,
-          kMockRenderFrameId, kMockProcessId,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId),
-          GetBadMessageCallback());
-      AppCacheHost* host2 = service_->GetHost(host2_id_);
-      network::ResourceRequest request;
-      request.url = GetMockUrl("manifest");
-      handler_ = host2->CreateRequestHandler(
-          std::make_unique<AppCacheRequest>(request),
-          network::mojom::RequestDestination::kDocument, false,
-          FrameTreeNode::kFrameTreeNodeInvalidId);
-      handler_->MaybeCreateLoader(request, nullptr, base::DoNothing(),
-                                  base::DoNothing());
-    }
-
-    PushNextTask(base::BindOnce(&AppCacheStorageImplTest::Verify_Reinitialized,
-                                base::Unretained(this), test_case));
-  }
-
-  void Verify_Reinitialized(ReinitTestCase test_case) {
-    // Verify we got notified of reinit and a new storage instance is created,
-    // and that the old data has been deleted.
-    EXPECT_TRUE(observer_->observed_old_storage_.get());
-    EXPECT_TRUE(observer_->observed_old_storage_->storage() != storage());
-    EXPECT_FALSE(PathExists(
-        temp_directory_.GetPath().AppendASCII("Cache").AppendASCII("index")));
-    EXPECT_FALSE(PathExists(temp_directory_.GetPath().AppendASCII("Index")));
-
-    if (test_case == CORRUPT_SQL_ON_INSTALL) {
-      AppCacheStorageImpl* storage = static_cast<AppCacheStorageImpl*>(
-          observer_->observed_old_storage_->storage());
-      EXPECT_TRUE(storage->database_->was_corruption_detected());
-    }
-
-    // Verify that the hosts saw appropriate events.
-    if (test_case == CORRUPT_CACHE_ON_INSTALL ||
-        test_case == CORRUPT_SQL_ON_INSTALL) {
-      EXPECT_TRUE(frontend_.error_event_was_raised_);
-      AppCacheHost* host1 = service_->GetHost(host1_id_);
-      EXPECT_FALSE(host1->associated_cache());
-      EXPECT_FALSE(host1->group_being_updated_.get());
-      EXPECT_TRUE(host1->disabled_storage_reference_.get());
-    } else {
-      ASSERT_EQ(CORRUPT_CACHE_ON_LOAD_EXISTING, test_case);
-      AppCacheHost* host2 = service_->GetHost(host2_id_);
-      EXPECT_TRUE(host2->disabled_storage_reference_.get());
-    }
-
-    // Cleanup and claim victory.
-    service_->EraseHost(host1_id_);
-    service_->EraseHost(host2_id_);
-    service_->RemoveObserver(observer_.get());
-    handler_.reset();
-    observer_.reset();
-    TestFinished();
-  }
-
-  // Test case helpers --------------------------------------------------
-
-  AppCacheServiceImpl* service() { return service_.get(); }
-
-  AppCacheStorageImpl* storage() {
-    return static_cast<AppCacheStorageImpl*>(service()->storage());
-  }
-
-  AppCacheDatabase* database() { return storage()->database_.get(); }
-
-  MockStorageDelegate* delegate() { return delegate_.get(); }
-
-  mojo::PendingRemote<blink::mojom::AppCacheFrontend> BindFrontend() {
-    mojo::PendingRemote<blink::mojom::AppCacheFrontend> result;
-    frontend_receivers_.Add(&frontend_,
-                            result.InitWithNewPipeAndPassReceiver());
-    return result;
-  }
-
-  mojo::ReportBadMessageCallback GetBadMessageCallback() {
-    return base::BindOnce(&AppCacheStorageImplTest::OnBadMessage,
-                          base::Unretained(this));
-  }
-
-  void OnBadMessage(const std::string& reason) { NOTREACHED(); }
-
-  static base::Time invalid_token_expires() { return base::Time(); }
-
-  static base::Time valid_token_expires() {
-    return base::Time::Now() + base::TimeDelta::FromDays(10);
-  }
-
-  void MakeCacheAndGroup(const GURL& manifest_url,
-                         int64_t group_id,
-                         int64_t cache_id,
-                         base::Time token_expires,
-                         bool add_to_database) {
-    AppCacheEntry default_entry(AppCacheEntry::EXPLICIT,
-                                cache_id + kDefaultEntryIdOffset,
-                                kDefaultEntrySize, kDefaultEntryPadding);
-    group_ =
-        base::MakeRefCounted<AppCacheGroup>(storage(), manifest_url, group_id);
-    cache_ = base::MakeRefCounted<AppCache>(storage(), cache_id);
-    cache_->AddEntry(kDefaultEntryUrl, default_entry);
-    cache_->set_complete(true);
-    group_->AddCache(cache_.get());
-    if (add_to_database)
-      AddToDatabase(manifest_url, group_id, cache_id, token_expires);
-  }
-
-  void AddToDatabase(const GURL& manifest_url,
-                     int64_t group_id,
-                     int64_t cache_id,
-                     base::Time token_expires) {
-    url::Origin manifest_origin(url::Origin::Create(manifest_url));
-    AppCacheEntry default_entry(AppCacheEntry::EXPLICIT,
-                                cache_id + kDefaultEntryIdOffset,
-                                kDefaultEntrySize, kDefaultEntryPadding);
-
-    AppCacheDatabase::GroupRecord group_record;
-    group_record.group_id = group_id;
-    group_record.manifest_url = manifest_url;
-    group_record.origin = manifest_origin;
-    EXPECT_TRUE(database()->InsertGroup(&group_record));
-    AppCacheDatabase::CacheRecord cache_record;
-    cache_record.cache_id = cache_id;
-    cache_record.group_id = group_id;
-    cache_record.online_wildcard = false;
-    cache_record.update_time = kZeroTime;
-    cache_record.cache_size = kDefaultEntrySize;
-    cache_record.padding_size = kDefaultEntryPadding;
-    cache_record.manifest_parser_version = 1;
-    cache_record.manifest_scope = std::string("/");
-    cache_record.token_expires = token_expires;
-    EXPECT_TRUE(database()->InsertCache(&cache_record));
-    AppCacheDatabase::EntryRecord entry_record;
-    entry_record.cache_id = cache_id;
-    entry_record.url = kDefaultEntryUrl;
-    entry_record.flags = default_entry.types();
-    entry_record.response_id = default_entry.response_id();
-    entry_record.response_size = default_entry.response_size();
-    entry_record.padding_size = default_entry.padding_size();
-    EXPECT_TRUE(database()->InsertEntry(&entry_record));
-
-    storage()->usage_map_[manifest_origin] =
-        default_entry.response_size() + default_entry.padding_size();
-  }
-
-  // Data members --------------------------------------------------
-  BrowserTaskEnvironment task_environment_;
-
-  base::OnceClosure test_finished_cb_;
-  base::stack<base::OnceClosure> task_stack_;
-  MockAppCachePolicy mock_policy_;
-  std::unique_ptr<AppCacheServiceImpl> service_;
-  std::unique_ptr<MockStorageDelegate> delegate_;
-  scoped_refptr<MockQuotaManagerProxy> mock_quota_manager_proxy_;
-  scoped_refptr<AppCacheGroup> group_;
-  scoped_refptr<AppCache> cache_;
-  scoped_refptr<AppCache> cache2_;
-
-  base::UnguessableToken host1_id_;
-  base::UnguessableToken host2_id_;
-  mojo::Remote<blink::mojom::AppCacheHost> host_remote_;
-
-  // Specifically for the Reinitalize test.
-  base::ScopedTempDir temp_directory_;
-  std::unique_ptr<MockServiceObserver> observer_;
-  MockAppCacheFrontend frontend_;
-  mojo::ReceiverSet<blink::mojom::AppCacheFrontend> frontend_receivers_;
-  std::unique_ptr<AppCacheRequestHandler> handler_;
-  URLLoaderInterceptor interceptor_;
-  TestBrowserContext browser_context_;
-  base::test::ScopedFeatureList appcache_require_origin_trial_feature_;
-  // Delayed initialization to avoid data races with feature list.
-  absl::optional<base::WeakPtrFactory<StoragePartitionImpl>>
-      weak_partition_factory_;
-
-  // Test data
-  const base::Time kZeroTime;
-  const GURL kManifestUrl = GURL("http://blah/manifest");
-  const GURL kManifestUrl2 = GURL("http://blah/manifest2");
-  const GURL kManifestUrl3 = GURL("http://blah/manifest3");
-  const GURL kEntryUrl = GURL("http://blah/entry");
-  const GURL kEntryUrl2 = GURL("http://blah/entry2");
-  const GURL kFallbackNamespace = GURL("http://blah/fallback_namespace/");
-  const GURL kFallbackNamespace2 =
-      GURL("http://blah/fallback_namespace/longer");
-  const GURL kFallbackTestUrl =
-      GURL("http://blah/fallback_namespace/longer/test");
-  const GURL kOnlineNamespace = GURL("http://blah/online_namespace");
-  const GURL kOnlineNamespaceWithinFallback =
-      GURL("http://blah/fallback_namespace/online/");
-  const GURL kInterceptNamespace = GURL("http://blah/intercept_namespace/");
-  const GURL kInterceptNamespace2 =
-      GURL("http://blah/intercept_namespace/longer/");
-  const GURL kInterceptTestUrl =
-      GURL("http://blah/intercept_namespace/longer/test");
-  const GURL kInterceptPatternNamespace =
-      GURL("http://blah/intercept_pattern/*/bar");
-  const GURL kInterceptPatternTestPositiveUrl =
-      GURL("http://blah/intercept_pattern/foo/bar");
-  const GURL kInterceptPatternTestNegativeUrl =
-      GURL("http://blah/intercept_pattern/foo/not_bar");
-  const GURL kFallbackPatternNamespace =
-      GURL("http://blah/fallback_pattern/*/bar");
-  const GURL kFallbackPatternTestPositiveUrl =
-      GURL("http://blah/fallback_pattern/foo/bar");
-  const GURL kFallbackPatternTestNegativeUrl =
-      GURL("http://blah/fallback_pattern/foo/not_bar");
-  const url::Origin kOrigin = url::Origin::Create(kManifestUrl.GetOrigin());
-
-  const int kManifestEntryIdOffset = 100;
-  const int kFallbackEntryIdOffset = 1000;
-
-  const GURL kDefaultEntryUrl =
-      GURL("http://blah/makecacheandgroup_default_entry");
-  const int kDefaultEntrySize = 10;
-  const int kDefaultEntryPadding = 10000;
-  const int kDefaultEntryIdOffset = 12345;
-};
-
-// By default AppCacheStorageImplTest disables the origin trial.
-// Specific tests use this to turn it back on.
-class AppCacheStorageImplTestEnableOriginTrial
-    : public AppCacheStorageImplTest {
- public:
-  AppCacheStorageImplTestEnableOriginTrial() {
-    appcache_require_origin_trial_feature_.InitAndEnableFeature(
-        blink::features::kAppCacheRequireOriginTrial);
-  }
-
- private:
-  base::test::ScopedFeatureList appcache_require_origin_trial_feature_;
-};
-
-TEST_F(AppCacheStorageImplTest, LoadCache_Miss) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadCache_Miss);
-}
-
-TEST_F(AppCacheStorageImplTest, LoadCache_NearHit) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadCache_NearHit);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial, LoadCache_OriginTrialSuccess) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadCache_OriginTrialSuccess);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial, LoadCache_OriginTrialFailure) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadCache_OriginTrialFailure);
-}
-
-TEST_F(AppCacheStorageImplTest, CreateGroupInEmptyOrigin) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::CreateGroupInEmptyOrigin);
-}
-
-TEST_F(AppCacheStorageImplTest, CreateGroupInPopulatedOrigin) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::CreateGroupInPopulatedOrigin);
-}
-
-TEST_F(AppCacheStorageImplTest, LoadGroupAndCache_FarHit) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadGroupAndCache_FarHit);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       LoadGroupAndCache_OriginTrialSuccess) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::LoadGroupAndCache_FarHit);
-}
-
-TEST_F(AppCacheStorageImplTest, StoreNewGroup) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::StoreNewGroup);
-}
-
-TEST_F(AppCacheStorageImplTest, StoreExistingGroup) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::StoreExistingGroup);
-}
-
-TEST_F(AppCacheStorageImplTest, StoreExistingGroupExistingCache) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::StoreExistingGroupExistingCache);
-}
-
-TEST_F(AppCacheStorageImplTest, FailStoreGroup_SizeTooBig) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::FailStoreGroup_SizeTooBig);
-}
-
-TEST_F(AppCacheStorageImplTest, FailStoreGroup_PaddingTooBig) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::FailStoreGroup_PaddingTooBig);
-}
-
-TEST_F(AppCacheStorageImplTest, MakeGroupObsolete) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::MakeGroupObsolete);
-}
-
-TEST_F(AppCacheStorageImplTest, MarkEntryAsForeign) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::MarkEntryAsForeign);
-}
-
-TEST_F(AppCacheStorageImplTest, MarkEntryAsForeignWithLoadInProgress) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::MarkEntryAsForeignWithLoadInProgress);
-}
-
-TEST_F(AppCacheStorageImplTest, FindNoMainResponse) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::FindNoMainResponse);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInDatabase) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::BasicFindMainResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       BasicFindMainResponse_OriginTrialFailure) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainResponse_OriginTrialFailure);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       BasicFindMainResponse_OriginTrialSuccess) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainResponseInWorkingSet) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainResponseInWorkingSet);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInDatabase) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainFallbackResponseInWorkingSet) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainFallbackResponseInWorkingSet);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       FindMainFallbackResponse_OriginTrialSuccess) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainFallbackResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       FindMainFallbackResponse_OriginTrialFailure) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::FindMainFallbackResponse_OriginTrialFailure);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInDatabase) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainInterceptResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTest, BasicFindMainInterceptResponseInWorkingSet) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainInterceptResponseInWorkingSet);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       FindMainInterceptResponse_OriginTrialSuccess) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::BasicFindMainInterceptResponseInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTestEnableOriginTrial,
-       FindMainInterceptResponse_OriginTrialFailure) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::FindMainInterceptResponse_OriginTrialFailure);
-}
-
-TEST_F(AppCacheStorageImplTest, FindMainResponseWithMultipleHits) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::FindMainResponseWithMultipleHits);
-}
-
-TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInDatabase) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::FindMainResponseExclusionsInDatabase);
-}
-
-TEST_F(AppCacheStorageImplTest, FindMainResponseExclusionsInWorkingSet) {
-  RunTestOnUIThread(
-      &AppCacheStorageImplTest::FindMainResponseExclusionsInWorkingSet);
-}
-
-TEST_F(AppCacheStorageImplTest, Reinitialize1) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::Reinitialize1);
-}
-
-TEST_F(AppCacheStorageImplTest, Reinitialize2) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::Reinitialize2);
-}
-
-TEST_F(AppCacheStorageImplTest, Reinitialize3) {
-  RunTestOnUIThread(&AppCacheStorageImplTest::Reinitialize3);
-}
-
-// That's all folks!
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_storage_unittest.cc b/content/browser/appcache/appcache_storage_unittest.cc
deleted file mode 100644
index 377f975..0000000
--- a/content/browser/appcache/appcache_storage_unittest.cc
+++ /dev/null
@@ -1,199 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_storage.h"
-
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "storage/browser/test/mock_quota_manager_proxy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/storage_key/storage_key.h"
-
-namespace content {
-namespace appcache_storage_unittest {
-
-const blink::mojom::StorageType kTemp = blink::mojom::StorageType::kTemporary;
-
-class AppCacheStorageTest : public testing::Test {
- public:
-  class MockStorageDelegate : public AppCacheStorage::Delegate {
-   public:
-  };
-
- private:
-  BrowserTaskEnvironment task_environment_;
-};
-
-TEST_F(AppCacheStorageTest, AddRemoveCache) {
-  MockAppCacheService service;
-  scoped_refptr<AppCache> cache =
-      base::MakeRefCounted<AppCache>(service.storage(), 111);
-
-  EXPECT_EQ(cache.get(),
-            service.storage()->working_set()->GetCache(111));
-
-  service.storage()->working_set()->RemoveCache(cache.get());
-
-  EXPECT_TRUE(!service.storage()->working_set()->GetCache(111));
-
-  // Removing non-existing cache from service should not fail.
-  MockAppCacheService dummy;
-  dummy.storage()->working_set()->RemoveCache(cache.get());
-}
-
-TEST_F(AppCacheStorageTest, AddRemoveGroup) {
-  MockAppCacheService service;
-  const GURL kManifestUrl("http://origin/");
-  scoped_refptr<AppCacheGroup> group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl, 111);
-
-  EXPECT_EQ(group.get(),
-            service.storage()->working_set()->GetGroup(kManifestUrl));
-
-  service.storage()->working_set()->RemoveGroup(group.get());
-
-  EXPECT_TRUE(!service.storage()->working_set()->GetGroup(kManifestUrl));
-
-  // Removing non-existing group from service should not fail.
-  MockAppCacheService dummy;
-  dummy.storage()->working_set()->RemoveGroup(group.get());
-}
-
-TEST_F(AppCacheStorageTest, AddRemoveResponseInfo) {
-  MockAppCacheService service;
-  const GURL kManifestUrl("http://origin/");
-  scoped_refptr<AppCacheResponseInfo> info =
-      base::MakeRefCounted<AppCacheResponseInfo>(
-          service.storage()->GetWeakPtr(), kManifestUrl, 111,
-          std::make_unique<net::HttpResponseInfo>(),
-          HttpResponseInfoIOBuffer::kUnknownResponseDataSize);
-
-  EXPECT_EQ(info.get(),
-            service.storage()->working_set()->GetResponseInfo(111));
-
-  service.storage()->working_set()->RemoveResponseInfo(info.get());
-
-  EXPECT_FALSE(service.storage()->working_set()->GetResponseInfo(111));
-
-  // Removing non-existing info from service should not fail.
-  MockAppCacheService dummy;
-  dummy.storage()->working_set()->RemoveResponseInfo(info.get());
-}
-
-TEST_F(AppCacheStorageTest, ResponseInfoLifetime) {
-  scoped_refptr<AppCacheResponseInfo> info;
-  {
-    MockAppCacheService service;
-    const GURL kManifestUrl("http://origin/");
-    info = base::MakeRefCounted<AppCacheResponseInfo>(
-        service.storage()->GetWeakPtr(), kManifestUrl, 111,
-        std::make_unique<net::HttpResponseInfo>(),
-        HttpResponseInfoIOBuffer::kUnknownResponseDataSize);
-
-    EXPECT_EQ(info.get(),
-              service.storage()->working_set()->GetResponseInfo(111));
-  }
-
-  // Outliving the AppCacheService should not be fatal.
-  info.reset();
-}
-
-TEST_F(AppCacheStorageTest, DelegateReferences) {
-  using ScopedDelegateReference =
-      scoped_refptr<AppCacheStorage::DelegateReference>;
-  MockAppCacheService service;
-  MockStorageDelegate delegate;
-  ScopedDelegateReference delegate_reference1;
-  ScopedDelegateReference delegate_reference2;
-
-  EXPECT_FALSE(service.storage()->GetDelegateReference(&delegate));
-
-  delegate_reference1 =
-      service.storage()->GetOrCreateDelegateReference(&delegate);
-  EXPECT_TRUE(delegate_reference1.get());
-  EXPECT_TRUE(delegate_reference1->HasOneRef());
-  EXPECT_TRUE(service.storage()->GetDelegateReference(&delegate));
-  EXPECT_EQ(&delegate,
-            service.storage()->GetDelegateReference(&delegate)->delegate);
-  EXPECT_EQ(service.storage()->GetDelegateReference(&delegate),
-            service.storage()->GetOrCreateDelegateReference(&delegate));
-  delegate_reference1 = nullptr;
-  EXPECT_FALSE(service.storage()->GetDelegateReference(&delegate));
-
-  delegate_reference1 =
-      service.storage()->GetOrCreateDelegateReference(&delegate);
-  service.storage()->CancelDelegateCallbacks(&delegate);
-  EXPECT_TRUE(delegate_reference1.get());
-  EXPECT_TRUE(delegate_reference1->HasOneRef());
-  EXPECT_FALSE(delegate_reference1->delegate);
-  EXPECT_FALSE(service.storage()->GetDelegateReference(&delegate));
-
-  delegate_reference2 =
-      service.storage()->GetOrCreateDelegateReference(&delegate);
-  EXPECT_TRUE(delegate_reference2.get());
-  EXPECT_TRUE(delegate_reference2->HasOneRef());
-  EXPECT_EQ(&delegate, delegate_reference2->delegate);
-  EXPECT_NE(delegate_reference1.get(), delegate_reference2.get());
-}
-
-TEST_F(AppCacheStorageTest, UsageMap) {
-  const url::Origin kOrigin(url::Origin::Create(GURL("http://origin/")));
-  const url::Origin kOrigin2(url::Origin::Create(GURL("http://origin2/")));
-
-  MockAppCacheService service;
-  auto mock_proxy = base::MakeRefCounted<storage::MockQuotaManagerProxy>(
-      nullptr, base::SequencedTaskRunnerHandle::Get());
-  service.set_quota_manager_proxy(mock_proxy.get());
-
-  service.storage()->UpdateUsageMapAndNotify(kOrigin, 0);
-  EXPECT_EQ(0, mock_proxy->notify_storage_modified_count());
-
-  service.storage()->UpdateUsageMapAndNotify(kOrigin, 10);
-  EXPECT_EQ(1, mock_proxy->notify_storage_modified_count());
-  EXPECT_EQ(10, mock_proxy->last_notified_delta());
-  EXPECT_EQ(blink::StorageKey(kOrigin),
-            mock_proxy->last_notified_storage_key());
-  EXPECT_EQ(kTemp, mock_proxy->last_notified_type());
-
-  service.storage()->UpdateUsageMapAndNotify(kOrigin, 100);
-  EXPECT_EQ(2, mock_proxy->notify_storage_modified_count());
-  EXPECT_EQ(90, mock_proxy->last_notified_delta());
-  EXPECT_EQ(blink::StorageKey(kOrigin),
-            mock_proxy->last_notified_storage_key());
-  EXPECT_EQ(kTemp, mock_proxy->last_notified_type());
-
-  service.storage()->UpdateUsageMapAndNotify(kOrigin, 0);
-  EXPECT_EQ(3, mock_proxy->notify_storage_modified_count());
-  EXPECT_EQ(-100, mock_proxy->last_notified_delta());
-  EXPECT_EQ(blink::StorageKey(kOrigin),
-            mock_proxy->last_notified_storage_key());
-  EXPECT_EQ(kTemp, mock_proxy->last_notified_type());
-
-  service.storage()->NotifyStorageAccessed(kOrigin2);
-  EXPECT_EQ(0, mock_proxy->notify_storage_accessed_count());
-
-  service.storage()->usage_map_[kOrigin2] = 1;
-  service.storage()->NotifyStorageAccessed(kOrigin2);
-  EXPECT_EQ(1, mock_proxy->notify_storage_accessed_count());
-  EXPECT_EQ(blink::StorageKey(kOrigin2),
-            mock_proxy->last_notified_storage_key());
-  EXPECT_EQ(kTemp, mock_proxy->last_notified_type());
-
-  service.storage()->usage_map_.clear();
-  service.storage()->usage_map_[kOrigin] = 5000;
-  service.storage()->ClearUsageMapAndNotify();
-  EXPECT_EQ(4, mock_proxy->notify_storage_modified_count());
-  EXPECT_EQ(-5000, mock_proxy->last_notified_delta());
-  EXPECT_EQ(blink::StorageKey(kOrigin),
-            mock_proxy->last_notified_storage_key());
-  EXPECT_EQ(kTemp, mock_proxy->last_notified_type());
-  EXPECT_TRUE(service.storage()->usage_map_.empty());
-}
-
-}  // namespace appcache_storage_unittest
-}  // namespace content
diff --git a/content/browser/appcache/appcache_unittest.cc b/content/browser/appcache/appcache_unittest.cc
deleted file mode 100644
index be3c40c..0000000
--- a/content/browser/appcache/appcache_unittest.cc
+++ /dev/null
@@ -1,575 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/macros.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_host.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-
-namespace content {
-
-class AppCacheTest : public testing::Test {
-  BrowserTaskEnvironment task_environment_;
-};
-
-TEST_F(AppCacheTest, CleanupUnusedCache) {
-  MockAppCacheService service;
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), 111);
-  cache->set_complete(true);
-  auto group = base::MakeRefCounted<AppCacheGroup>(
-      service.storage(), GURL("http://blah/manifest"), 111);
-  group->AddCache(cache.get());
-
-  mojo::PendingRemote<blink::mojom::AppCacheFrontend> frontend1;
-  ignore_result(frontend1.InitWithNewPipeAndPassReceiver());
-  const int kMockProcessId1 = 1;
-  const int kMockProcessId2 = 2;
-  AppCacheHost host1(
-      /*host_id=*/base::UnguessableToken::Create(), kMockProcessId1,
-      /*render_frame_id=*/1,
-      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-          kMockProcessId1),
-      std::move(frontend1), &service);
-
-  mojo::PendingRemote<blink::mojom::AppCacheFrontend> frontend2;
-  ignore_result(frontend2.InitWithNewPipeAndPassReceiver());
-  AppCacheHost host2(
-      /*host_id=*/base::UnguessableToken::Create(), kMockProcessId2,
-      /*render_frame_id=*/2,
-      ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-          kMockProcessId2),
-      std::move(frontend2), &service);
-
-  host1.AssociateCompleteCache(cache.get());
-  host2.AssociateCompleteCache(cache.get());
-
-  host1.AssociateNoCache(GURL());
-  host2.AssociateNoCache(GURL());
-}
-
-TEST_F(AppCacheTest, AddModifyRemoveEntry) {
-  MockAppCacheService service;
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), 111);
-
-  EXPECT_TRUE(cache->entries().empty());
-  EXPECT_EQ(0L, cache->cache_size());
-  EXPECT_EQ(0L, cache->padding_size());
-
-  const GURL kFooUrl("http://foo.com");
-  const int64_t kFooResponseId = 1;
-  const int64_t kFooSize = 100;
-  AppCacheEntry entry1(AppCacheEntry::MASTER, kFooResponseId,
-                       /*response_size=*/kFooSize,
-                       /*padding_size=*/0);
-  cache->AddEntry(kFooUrl, entry1);
-  EXPECT_EQ(entry1.types(), cache->GetEntry(kFooUrl)->types());
-  EXPECT_EQ(1UL, cache->entries().size());
-  EXPECT_EQ(kFooSize, cache->cache_size());
-  EXPECT_EQ(0L, cache->padding_size());
-
-  const GURL kBarUrl("http://bar.com");
-  const int64_t kBarResponseId = 2;
-  const int64_t kBarSize = 200;
-  AppCacheEntry entry2(AppCacheEntry::FALLBACK, kBarResponseId,
-                       /*response_size=*/kBarSize,
-                       /*padding_size=*/2 * kBarSize);
-  EXPECT_TRUE(cache->AddOrModifyEntry(kBarUrl, entry2));
-  EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types());
-  EXPECT_EQ(2UL, cache->entries().size());
-  EXPECT_EQ(kFooSize + kBarSize, cache->cache_size());
-  EXPECT_EQ(2 * kBarSize, cache->padding_size());
-
-  // Expected to return false when an existing entry is modified.
-  AppCacheEntry entry3(AppCacheEntry::EXPLICIT);
-  EXPECT_FALSE(cache->AddOrModifyEntry(kFooUrl, entry3));
-  EXPECT_EQ((AppCacheEntry::MASTER | AppCacheEntry::EXPLICIT),
-            cache->GetEntry(kFooUrl)->types());
-  // Only the type should be modified.
-  EXPECT_EQ(kFooResponseId, cache->GetEntry(kFooUrl)->response_id());
-  EXPECT_EQ(kFooSize, cache->GetEntry(kFooUrl)->response_size());
-  EXPECT_EQ(kFooSize + kBarSize, cache->cache_size());
-  EXPECT_EQ(2 * kBarSize, cache->padding_size());
-
-  EXPECT_EQ(entry2.types(), cache->GetEntry(kBarUrl)->types());  // unchanged
-
-  cache->RemoveEntry(kBarUrl);
-  EXPECT_EQ(kFooSize, cache->cache_size());
-  cache->RemoveEntry(kFooUrl);
-  EXPECT_EQ(0L, cache->cache_size());
-  EXPECT_EQ(0L, cache->padding_size());
-  EXPECT_TRUE(cache->entries().empty());
-}
-
-TEST_F(AppCacheTest, InitializeWithManifest) {
-  MockAppCacheService service;
-
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), 1234);
-  EXPECT_TRUE(cache->fallback_namespaces_.empty());
-  EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-  EXPECT_FALSE(cache->online_safelist_all_);
-
-  AppCacheManifest manifest;
-  manifest.explicit_urls.insert("http://one.com");
-  manifest.explicit_urls.insert("http://two.com");
-  manifest.fallback_namespaces.push_back(
-      AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE, GURL("http://fb1.com"),
-                        GURL("http://fbone.com")));
-  manifest.online_safelist_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_NETWORK_NAMESPACE, GURL("http://w1.com"), GURL()));
-  manifest.online_safelist_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_NETWORK_NAMESPACE, GURL("http://w2.com"), GURL()));
-  manifest.online_safelist_all = true;
-
-  cache->InitializeWithManifest(&manifest);
-  const std::vector<AppCacheNamespace>& fallbacks =
-      cache->fallback_namespaces_;
-  size_t expected = 1;
-  EXPECT_EQ(expected, fallbacks.size());
-  EXPECT_EQ(GURL("http://fb1.com"), fallbacks[0].namespace_url);
-  EXPECT_EQ(GURL("http://fbone.com"), fallbacks[0].target_url);
-  const std::vector<AppCacheNamespace>& safelist =
-      cache->online_safelist_namespaces_;
-  expected = 2;
-  EXPECT_EQ(expected, safelist.size());
-  EXPECT_EQ(GURL("http://w1.com"), safelist[0].namespace_url);
-  EXPECT_EQ(GURL("http://w2.com"), safelist[1].namespace_url);
-  EXPECT_TRUE(cache->online_safelist_all_);
-
-  // Ensure collections in manifest were taken over by the cache rather than
-  // copied.
-  EXPECT_TRUE(manifest.fallback_namespaces.empty());
-  EXPECT_TRUE(manifest.online_safelist_namespaces.empty());
-}
-
-TEST_F(AppCacheTest, FindResponseForRequest) {
-  MockAppCacheService service;
-
-  const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
-  const GURL kFallbackEntryUrl1("http://blah/fallback_entry1");
-  const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/");
-  const GURL kFallbackEntryUrl2("http://blah/fallback_entry2");
-  const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer");
-  const GURL kManifestUrl("http://blah/manifest");
-  const GURL kForeignExplicitEntryUrl("http://blah/foreign");
-  const GURL kInOnlineNamespaceUrl(
-      "http://blah/online_namespace/network");
-  const GURL kExplicitInOnlineNamespaceUrl(
-      "http://blah/online_namespace/explicit");
-  const GURL kFallbackTestUrl1("http://blah/fallback_namespace/1");
-  const GURL kFallbackTestUrl2("http://blah/fallback_namespace/longer2");
-  const GURL kInterceptNamespace("http://blah/intercept_namespace/");
-  const GURL kInterceptNamespaceWithinFallback(
-      "http://blah/fallback_namespace/intercept_namespace/");
-  const GURL kInterceptNamespaceEntry("http://blah/intercept_entry");
-  const GURL kOnlineNamespaceWithinOtherNamespaces(
-      "http://blah/fallback_namespace/intercept_namespace/1/online");
-
-  const int64_t kFallbackResponseId1 = 1;
-  const int64_t kFallbackResponseId2 = 2;
-  const int64_t kManifestResponseId = 3;
-  const int64_t kForeignExplicitResponseId = 4;
-  const int64_t kExplicitInOnlineNamespaceResponseId = 5;
-  const int64_t kInterceptResponseId = 6;
-
-  AppCacheManifest manifest;
-  manifest.online_safelist_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl, GURL()));
-  manifest.online_safelist_namespaces.push_back(
-      AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
-                        kOnlineNamespaceWithinOtherNamespaces, GURL()));
-  manifest.fallback_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, kFallbackEntryUrl1));
-  manifest.fallback_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, kFallbackEntryUrl2));
-  manifest.intercept_namespaces.push_back(
-      AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespace,
-                        kInterceptNamespaceEntry));
-  manifest.intercept_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_INTERCEPT_NAMESPACE, kInterceptNamespaceWithinFallback,
-      kInterceptNamespaceEntry));
-
-  // Create a cache with some namespaces and entries.
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), 1234);
-  cache->InitializeWithManifest(&manifest);
-  cache->AddEntry(
-      kFallbackEntryUrl1,
-      AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId1));
-  cache->AddEntry(
-      kFallbackEntryUrl2,
-      AppCacheEntry(AppCacheEntry::FALLBACK, kFallbackResponseId2));
-  cache->AddEntry(
-      kManifestUrl,
-      AppCacheEntry(AppCacheEntry::MANIFEST, kManifestResponseId));
-  cache->AddEntry(
-      kForeignExplicitEntryUrl,
-      AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
-                    kForeignExplicitResponseId));
-  cache->AddEntry(
-      kExplicitInOnlineNamespaceUrl,
-      AppCacheEntry(AppCacheEntry::EXPLICIT,
-                    kExplicitInOnlineNamespaceResponseId));
-  cache->AddEntry(
-      kInterceptNamespaceEntry,
-      AppCacheEntry(AppCacheEntry::INTERCEPT, kInterceptResponseId));
-  cache->set_complete(true);
-
-  // See that we get expected results from FindResponseForRequest
-
-  bool found = false;
-  AppCacheEntry entry;
-  AppCacheEntry fallback_entry;
-  GURL intercept_namespace;
-  GURL fallback_namespace;
-  bool network_namespace = false;
-
-  found = cache->FindResponseForRequest(GURL("http://blah/miss"),
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_FALSE(found);
-
-  found = cache->FindResponseForRequest(kForeignExplicitEntryUrl,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_EQ(kForeignExplicitResponseId, entry.response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_FALSE(network_namespace);
-
-  entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(kManifestUrl,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_EQ(kManifestResponseId, entry.response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_FALSE(network_namespace);
-
-  entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(kInOnlineNamespaceUrl,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_FALSE(entry.has_response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_TRUE(network_namespace);
-
-  network_namespace = false;  // reset
-
-  found = cache->FindResponseForRequest(kExplicitInOnlineNamespaceUrl,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_EQ(kExplicitInOnlineNamespaceResponseId, entry.response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_FALSE(network_namespace);
-
-  entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(kFallbackTestUrl1,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_FALSE(entry.has_response_id());
-  EXPECT_EQ(kFallbackResponseId1, fallback_entry.response_id());
-  EXPECT_EQ(kFallbackEntryUrl1,
-            cache->GetFallbackEntryUrl(fallback_namespace));
-  EXPECT_FALSE(network_namespace);
-
-  fallback_entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(kFallbackTestUrl2,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_FALSE(entry.has_response_id());
-  EXPECT_EQ(kFallbackResponseId2, fallback_entry.response_id());
-  EXPECT_EQ(kFallbackEntryUrl2,
-            cache->GetFallbackEntryUrl(fallback_namespace));
-  EXPECT_FALSE(network_namespace);
-
-  fallback_entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(kOnlineNamespaceWithinOtherNamespaces,
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_FALSE(entry.has_response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_TRUE(network_namespace);
-
-  fallback_entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(
-      kOnlineNamespaceWithinOtherNamespaces.Resolve("online_resource"),
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_FALSE(entry.has_response_id());
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_TRUE(network_namespace);
-
-  fallback_namespace = GURL();
-
-  found = cache->FindResponseForRequest(
-      kInterceptNamespace.Resolve("intercept_me"),
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_EQ(kInterceptResponseId, entry.response_id());
-  EXPECT_EQ(kInterceptNamespaceEntry,
-            cache->GetInterceptEntryUrl(intercept_namespace));
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_TRUE(fallback_namespace.is_empty());
-  EXPECT_FALSE(network_namespace);
-
-  entry = AppCacheEntry();  // reset
-
-  found = cache->FindResponseForRequest(
-      kInterceptNamespaceWithinFallback.Resolve("intercept_me"),
-      &entry, &intercept_namespace,
-      &fallback_entry, &fallback_namespace,
-      &network_namespace);
-  EXPECT_TRUE(found);
-  EXPECT_EQ(kInterceptResponseId, entry.response_id());
-  EXPECT_EQ(kInterceptNamespaceEntry,
-            cache->GetInterceptEntryUrl(intercept_namespace));
-  EXPECT_FALSE(fallback_entry.has_response_id());
-  EXPECT_TRUE(fallback_namespace.is_empty());
-  EXPECT_FALSE(network_namespace);
-}
-
-TEST_F(AppCacheTest, ToFromDatabaseRecords) {
-  // Setup a cache with some entries.
-  const int64_t kCacheId = 1234;
-  const int64_t kGroupId = 4321;
-  const GURL kManifestUrl("http://foo.com/manifest");
-  const std::string kManifestScope = kManifestUrl.GetWithoutFilename().path();
-  const GURL kInterceptUrl("http://foo.com/intercept.html");
-  const GURL kFallbackUrl("http://foo.com/fallback.html");
-  const GURL kPatternSafelistUrl("http://foo.com/patternsafelist*");
-  const GURL kSafelistUrl("http://foo.com/safelist");
-  const std::string kData(
-      "CACHE MANIFEST\r"
-      "CHROMIUM-INTERCEPT:\r"
-      "/intercept return /intercept.html\r"
-      "FALLBACK:\r"
-      "/ /fallback.html\r"
-      "NETWORK:\r"
-      "/patternsafelist* isPattern\r"
-      "/safelist\r"
-      "*\r");
-
-  MockAppCacheService service;
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId);
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   kManifestUrl, kGroupId);
-  AppCacheManifest manifest;
-  EXPECT_TRUE(
-      ParseManifest(kManifestUrl, kManifestScope, kData.c_str(), kData.length(),
-                    PARSE_MANIFEST_ALLOWING_DANGEROUS_FEATURES, manifest));
-  cache->InitializeWithManifest(&manifest);
-  EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
-            cache->online_safelist_namespaces_[0].type);
-  EXPECT_EQ(kPatternSafelistUrl,
-            cache->online_safelist_namespaces_[0].namespace_url);
-  EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
-            cache->online_safelist_namespaces_[1].type);
-  EXPECT_EQ(kSafelistUrl, cache->online_safelist_namespaces_[1].namespace_url);
-  cache->AddEntry(kManifestUrl, AppCacheEntry(AppCacheEntry::MANIFEST,
-                                              /*response_id=*/1,
-                                              /*response_size=*/1000,
-                                              /*padding_size=*/0));
-  cache->AddEntry(kInterceptUrl, AppCacheEntry(AppCacheEntry::INTERCEPT,
-                                               /*response_id=*/3,
-                                               /*response_size=*/10000,
-                                               /*padding_size=*/10));
-  cache->AddEntry(kFallbackUrl, AppCacheEntry(AppCacheEntry::FALLBACK,
-                                              /*response_id=*/2,
-                                              /*response_size=*/100000,
-                                              /*padding_size=*/100));
-
-  // Get it to produce database records and verify them.
-  AppCacheDatabase::CacheRecord cache_record;
-  std::vector<AppCacheDatabase::EntryRecord> entries;
-  std::vector<AppCacheDatabase::NamespaceRecord> intercepts;
-  std::vector<AppCacheDatabase::NamespaceRecord> fallbacks;
-  std::vector<AppCacheDatabase::OnlineSafeListRecord> safelists;
-  cache->ToDatabaseRecords(group.get(), &cache_record, &entries, &intercepts,
-                           &fallbacks, &safelists);
-  EXPECT_EQ(kCacheId, cache_record.cache_id);
-  EXPECT_EQ(kGroupId, cache_record.group_id);
-  EXPECT_TRUE(cache_record.online_wildcard);
-  EXPECT_EQ(1000 + 10000 + 100000, cache_record.cache_size);
-  EXPECT_EQ(0 + 10 + 100, cache_record.padding_size);
-  EXPECT_EQ(3u, entries.size());
-  EXPECT_EQ(1u, intercepts.size());
-  EXPECT_EQ(1u, fallbacks.size());
-  EXPECT_EQ(2u, safelists.size());
-  cache = nullptr;
-
-  // Create a new AppCache and populate it with those records and verify.
-  cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId);
-  cache->InitializeWithDatabaseRecords(cache_record, entries, intercepts,
-                                       fallbacks, safelists);
-  EXPECT_TRUE(cache->online_safelist_all_);
-  EXPECT_EQ(3u, cache->entries().size());
-  EXPECT_TRUE(cache->GetEntry(kManifestUrl));
-  EXPECT_TRUE(cache->GetEntry(kInterceptUrl));
-  EXPECT_TRUE(cache->GetEntry(kFallbackUrl));
-  EXPECT_EQ(kInterceptUrl,
-            cache->GetInterceptEntryUrl(GURL("http://foo.com/intercept")));
-  EXPECT_EQ(kFallbackUrl,
-            cache->GetFallbackEntryUrl(GURL("http://foo.com/")));
-  EXPECT_EQ(1000 + 10000 + 100000, cache->cache_size());
-  EXPECT_EQ(0 + 10 + 100, cache->padding_size());
-  EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
-            cache->online_safelist_namespaces_[0].type);
-  EXPECT_EQ(kPatternSafelistUrl,
-            cache->online_safelist_namespaces_[0].namespace_url);
-  EXPECT_EQ(APPCACHE_NETWORK_NAMESPACE,
-            cache->online_safelist_namespaces_[1].type);
-  EXPECT_EQ(kSafelistUrl, cache->online_safelist_namespaces_[1].namespace_url);
-}
-
-TEST_F(AppCacheTest, IsNamespaceMatch) {
-  AppCacheNamespace prefix;
-  prefix.namespace_url = GURL("http://foo.com/prefix");
-  EXPECT_TRUE(prefix.IsMatch(GURL("http://foo.com/prefix")));
-  EXPECT_TRUE(prefix.IsMatch(
-      GURL("http://foo.com/prefix_and_anothing_goes")));
-  EXPECT_TRUE(prefix.IsMatch(GURL("http://foo.com/prefix/this_too")));
-  EXPECT_TRUE(prefix.IsMatch(GURL("http://foo.com/prefix/")));
-  EXPECT_FALSE(prefix.IsMatch(
-      GURL("http://foo.com/nope")));
-
-  // The following tests ensure that wildcards are not supported. Chrome used
-  // to support an `isPattern` extension enabling wildcard matching.
-  AppCacheNamespace bar_star;
-  bar_star.namespace_url = GURL("http://foo.com/bar/*");
-  EXPECT_FALSE(bar_star.IsMatch(GURL("http://foo.com/bar/")));
-  EXPECT_FALSE(bar_star.IsMatch(GURL("http://foo.com/bar/should_not_match")));
-  EXPECT_FALSE(
-      bar_star.IsMatch(GURL("http://foo.com/not_bar/should_not_match")));
-
-  AppCacheNamespace star_bar_star;
-  star_bar_star.namespace_url = GURL("http://foo.com/*/bar/*");
-  EXPECT_FALSE(
-      star_bar_star.IsMatch(GURL("http://foo.com/any/bar/should_not_match")));
-  EXPECT_FALSE(star_bar_star.IsMatch(GURL("http://foo.com/any/bar/")));
-  EXPECT_FALSE(star_bar_star.IsMatch(
-      GURL("http://foo.com/any/not_bar/no_match")));
-
-  AppCacheNamespace query_star_edit;
-  query_star_edit.namespace_url = GURL("http://foo.com/query?id=*&verb=edit*");
-  EXPECT_FALSE(query_star_edit.IsMatch(
-      GURL("http://foo.com/query?id=1234&verb=edit&option=blue")));
-  EXPECT_FALSE(query_star_edit.IsMatch(
-      GURL("http://foo.com/query?id=12345&option=blue&verb=edit")));
-  EXPECT_FALSE(query_star_edit.IsMatch(
-      GURL("http://foo.com/query?id=12345&option=blue&verb=print")));
-  EXPECT_FALSE(query_star_edit.IsMatch(
-      GURL("http://foo.com/query?id=123&verb=print&verb=edit")));
-}
-
-TEST_F(AppCacheTest, CheckValidManifestScopeTests) {
-  EXPECT_TRUE(
-      AppCache::CheckValidManifestScope(GURL("http://mockhost/manifest"), "/"));
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "/foo/"));
-
-  // Check that a relative scope is allowed.
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "bar/"));
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "../"));
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "../foo/"));
-  // Relative past the top of the path should be equal to both "../" and "/"
-  // (and hence valid).
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "../../"));
-
-  // A scope must be non-empty.
-  EXPECT_FALSE(
-      AppCache::CheckValidManifestScope(GURL("http://mockhost/manifest"), ""));
-
-  // Check that scope must end in a slash.
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "/foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "bar"));
-  EXPECT_TRUE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), ".."));
-
-  // Test invalid scopes.
-  EXPECT_FALSE(
-      AppCache::CheckValidManifestScope(GURL("http://mockhost/manifest"), " "));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "\t"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "\n"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "?foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "/?foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "../?foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "#foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "/#foo"));
-  EXPECT_FALSE(AppCache::CheckValidManifestScope(
-      GURL("http://mockhost/manifest"), "../#foo"));
-}
-
-TEST_F(AppCacheTest, GetManifestScopeTests) {
-  // Test the defaults.
-  EXPECT_EQ(AppCache::GetManifestScope(GURL("http://mockhost/manifest"), ""),
-            "/");
-  EXPECT_EQ(
-      AppCache::GetManifestScope(GURL("http://mockhost/foo/manifest"), ""),
-      "/foo/");
-
-  // Test the overrides.
-  EXPECT_EQ(AppCache::GetManifestScope(GURL("http://mockhost/manifest"), "/"),
-            "/");
-  EXPECT_EQ(
-      AppCache::GetManifestScope(GURL("http://mockhost/foo/manifest"), "/"),
-      "/");
-  EXPECT_EQ(
-      AppCache::GetManifestScope(GURL("http://mockhost/foo/manifest"), "../"),
-      "../");
-
-  // Relative past the top of the path should be equal to both "../" and "/"
-  // (and hence valid), so we keep it as it was passed to us.
-  EXPECT_EQ(
-      AppCache::GetManifestScope(GURL("http://mockhost/manifest"), "../../"),
-      "../../");
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/appcache_update_job_unittest.cc b/content/browser/appcache/appcache_update_job_unittest.cc
deleted file mode 100644
index df77c8d..0000000
--- a/content/browser/appcache/appcache_update_job_unittest.cc
+++ /dev/null
@@ -1,5822 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/appcache_update_job.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/containers/contains.h"
-#include "base/cxx17_backports.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/strcat.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_cache_test_helper.h"
-#include "content/browser/appcache/appcache_disk_cache_ops.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_host.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/appcache_update_url_loader_request.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/storage_partition_impl.h"
-#include "content/browser/url_loader_factory_getter.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/origin_util.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "content/public/test/url_loader_interceptor.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "mojo/public/cpp/system/data_pipe.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "services/network/public/mojom/url_loader.mojom.h"
-#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/features.h"
-#include "third_party/blink/public/common/origin_trials/scoped_test_origin_trial_policy.h"
-#include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-#include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
-
-namespace {
-// tools/origin_trials/generate_token.py http://mockhost AppCache
-// --expire-days=2000
-//
-// tools/origin_trials/check_token.py extracts token expiry: 1761166418.
-#define APPCACHE_ORIGIN_TRIAL_TOKEN                                            \
-  "AhiiB7vi3JiEO1/"                                                            \
-  "RQIytQslLSN3WYVu3Xd32abYhTia+91ladjnXSClfU981x+"                            \
-  "aoPimEqYVy6tWoeMZZYTpqlggAAABNeyJvcmlnaW4iOiAiaHR0cDovL21vY2tob3N0OjgwIiwg" \
-  "ImZlYXR1cmUiOiAiQXBwQ2FjaGUiLCAiZXhwaXJ5IjogMTc2MTE2NjQxOH0="
-
-const base::Time kTestOriginTrialTokenExpiry =
-    base::Time::FromDoubleT(1761166418);
-}  // namespace
-
-namespace content {
-
-namespace appcache_update_job_unittest {
-
-class AppCacheUpdateJobTest;
-
-// Values should match values used in appcache_update_job.cc.
-const base::TimeDelta kFullUpdateInterval = base::TimeDelta::FromHours(24);
-const base::TimeDelta kMaxEvictableErrorDuration =
-    base::TimeDelta::FromDays(14);
-const base::TimeDelta kOneHour = base::TimeDelta::FromHours(1);
-const base::TimeDelta kOneYear = base::TimeDelta::FromDays(365);
-
-const char kManifest1Contents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "NETWORK:\n"
-    "*\n";
-
-const char kManifest1OriginTrialContents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "ORIGIN-TRIAL:\n" APPCACHE_ORIGIN_TRIAL_TOKEN
-    "\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "NETWORK:\n"
-    "*\n";
-
-const char kManifest1WithNotModifiedContents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "NETWORK:\n"
-    "*\n"
-    "CACHE:\n"
-    "notmodified\n";
-
-const char kManifest1WithMaybeModifiedContents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "NETWORK:\n"
-    "*\n"
-    "CACHE:\n"
-    "maybemodified\n";
-
-const char kExplicit1Contents[] = "explicit1";
-
-// By default, kManifest2Contents is served from a path in /files/, so any
-// resource listing in it that references outside of that path will require a
-// scope override to be stored.
-const char kManifest2Contents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "CHROMIUM-INTERCEPT:\n"
-    "intercept1 return intercept1a\n"
-    "/bar/intercept2 return intercept2a\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "/bar/fallback2 fallback2a\n"
-    "NETWORK:\n"
-    "*\n";
-
-const char kManifest2OriginTrialContents[] =
-    "CACHE MANIFEST\n"
-    "explicit1\n"
-    "CHROMIUM-INTERCEPT:\n"
-    "intercept1 return intercept1a\n"
-    "/bar/intercept2 return intercept2a\n"
-    "ORIGIN-TRIAL:\n" APPCACHE_ORIGIN_TRIAL_TOKEN
-    "\n"
-    "FALLBACK:\n"
-    "fallback1 fallback1a\n"
-    "/bar/fallback2 fallback2a\n"
-    "NETWORK:\n"
-    "*\n";
-
-const char kScopeManifestContents[] =
-    "CACHE MANIFEST\n"
-    "CHROMIUM-INTERCEPT:\n"
-    "/bar/foo return /intercept-newbar/foo\n"
-    "/bar/baz/foo return /intercept-newbar/newbaz/foo\n"
-    "/other/foo return /intercept-newother/foo\n"
-    "/ return /intercept-newroot/foo\n"
-    "FALLBACK:\n"
-    "/bar/foo /fallback-newbar/foo\n"
-    "/bar/baz/foo /fallback-newbar/newbaz/foo\n"
-    "/other/foo /fallback-newother/foo\n"
-    "/ /fallback-newroot/foo\n";
-
-// There are a handful of http accessible resources that we need to conduct
-// these tests. Instead of running a separate server to host these resources,
-// we mock them up.
-class MockHttpServer {
- public:
-  static url::Origin GetOrigin() {
-    return url::Origin::Create(GURL("http://mockhost"));
-  }
-
-  static GURL GetMockUrl(const std::string& path) {
-    return GURL("http://mockhost/" + path);
-  }
-
-  static GURL GetMockHttpsUrl(const std::string& path) {
-    return GURL("https://mockhost/" + path);
-  }
-
-  static GURL GetMockCrossOriginHttpsUrl(const std::string& path) {
-    return GURL("https://cross_origin_host/" + path);
-  }
-
-  static std::string GetManifestHeaders(const bool ok,
-                                        const std::string& scope) {
-    std::string headers;
-    if (ok)
-      headers += "HTTP/1.1 200 OK\n";
-    else
-      headers += "HTTP/1.1 304 NOT MODIFIED\n";
-    headers += "Content-type: text/cache-manifest\n";
-    if (!scope.empty())
-      headers += "X-AppCache-Allowed: " + scope + "\n";
-    headers += "\n";
-    return headers;
-  }
-
-  static void GetMockResponse(const std::string& path,
-                              std::string* headers,
-                              std::string* body) {
-    const char ok_headers[] =
-        "HTTP/1.1 200 OK\n"
-        "\n";
-    const char error_headers[] =
-        "HTTP/1.1 500 BOO HOO\n"
-        "\n";
-    const char manifest_headers[] =
-        "HTTP/1.1 200 OK\n"
-        "Content-type: text/cache-manifest\n"
-        "\n";
-    const char not_modified_headers[] =
-        "HTTP/1.1 304 NOT MODIFIED\n"
-        "X-AppCache-Allowed: /\n"
-        "\n";
-    const char gone_headers[] =
-        "HTTP/1.1 410 GONE\n"
-        "\n";
-    const char not_found_headers[] =
-        "HTTP/1.1 404 NOT FOUND\n"
-        "\n";
-    const char no_store_headers[] =
-        "HTTP/1.1 200 OK\n"
-        "Cache-Control: no-store\n"
-        "\n";
-
-    if (path == "/files/missing-mime-manifest") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "CACHE MANIFEST\n";
-    } else if (path == "/files/bad-manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = "BAD CACHE MANIFEST";
-    } else if (path == "/files/empty1") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "";
-    } else if (path == "/files/empty-file-manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "empty1\n";
-    } else if (path == "/files/empty-manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = "CACHE MANIFEST\n";
-    } else if (path == "/files/explicit1") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = kExplicit1Contents;
-    } else if (path == "/files/explicit2") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "explicit2";
-    } else if (path == "/files/fallback1a") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "fallback1a";
-    } else if (path == "/files/fallback2a") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "fallback2a";
-    } else if (path == "/files/intercept1a") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "intercept1a";
-    } else if (path == "/files/intercept2a") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "intercept2a";
-    } else if (path == "/files/gone") {
-      (*headers) = std::string(gone_headers, base::size(gone_headers));
-      (*body) = "";
-    } else if (path == "/files/manifest1") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = kManifest1Contents;
-    } else if (path == "/files/manifest2") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = kManifest2Contents;
-    } else if (path == "/files/manifest2-origin-trial") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = kManifest2OriginTrialContents;
-    } else if (path == "/files/manifest2-with-root-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/true, /*scope=*/"/");
-      (*body) = kManifest2Contents;
-    } else if (path == "/files/manifest1-with-notmodified") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = kManifest1WithNotModifiedContents;
-    } else if (path == "/files/manifest1-with-maybemodified") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) = kManifest1WithMaybeModifiedContents;
-    } else if (path == "/files/manifest-fb-404") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "explicit1\n"
-          "FALLBACK:\n"
-          "fallback1 fallback1a\n"
-          "fallback404 fallback-404\n"
-          "NETWORK:\n"
-          "online1\n";
-    } else if (path == "/files/manifest-merged-types") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "explicit1\n"
-          "# manifest is also an explicit entry\n"
-          "manifest-merged-types\n"
-          "FALLBACK:\n"
-          "# fallback is also explicit entry\n"
-          "fallback1 explicit1\n"
-          "NETWORK:\n"
-          "online1\n";
-    } else if (path == "/files/manifest-with-404") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "explicit-404\n"
-          "explicit1\n"
-          "explicit2\n"
-          "explicit3\n"
-          "FALLBACK:\n"
-          "fallback1 fallback1a\n"
-          "NETWORK:\n"
-          "online1\n";
-    } else if (path == "/files/manifest-with-intercept") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "CHROMIUM-INTERCEPT:\n"
-          "intercept1 return intercept1a\n";
-    } else if (path == "/files/maybemodified") {
-      (*headers) =
-          std::string(not_modified_headers, base::size(not_modified_headers));
-      (*body) = "maybemodified";
-    } else if (path == "/files/modified") {
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "modified";
-    } else if (path == "/files/notmodified") {
-      (*headers) =
-          std::string(not_modified_headers, base::size(not_modified_headers));
-      (*body) = "";
-    } else if (path == "/files/servererror") {
-      (*headers) = std::string(error_headers, base::size(error_headers));
-      (*body) = "error";
-    } else if (path == "/files/valid_cross_origin_https_manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "https://cross_origin_host/files/explicit1\n";
-    } else if (path == "/files/invalid_cross_origin_https_manifest") {
-      (*headers) = std::string(manifest_headers, base::size(manifest_headers));
-      (*body) =
-          "CACHE MANIFEST\n"
-          "https://cross_origin_host/files/no-store-headers\n";
-    } else if (path == "/files/no-store-headers") {
-      (*headers) = std::string(no_store_headers, base::size(no_store_headers));
-      (*body) = "no-store";
-    } else if (path == "/intercept-newbar/foo" ||
-               path == "/intercept-newbar/newbaz/foo" ||
-               path == "/intercept-newother/foo" ||
-               path == "/intercept-newroot/foo" ||
-               path == "/fallback-newbar/foo" ||
-               path == "/fallback-newbar/newbaz/foo" ||
-               path == "/fallback-newother/foo" ||
-               path == "/fallback-newroot/foo") {
-      // Store mock responses for fallback resources needed by
-      // kScopeManifestContents.
-      (*headers) = std::string(ok_headers, base::size(ok_headers));
-      (*body) = "intercept/fallback contents";
-    } else if (path == "/manifest-no-override" ||
-               path == "/bar/manifest-no-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/true, /*scope=*/"");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-root-override" ||
-               path == "/bar/manifest-root-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/true, /*scope=*/"/");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-bar-override" ||
-               path == "/bar/manifest-bar-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/true, /*scope=*/"/bar/");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-other-override" ||
-               path == "/bar/manifest-other-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/true, /*scope=*/"/other/");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-304-no-override" ||
-               path == "/bar/manifest-304-no-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/false, /*scope=*/"");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-304-root-override" ||
-               path == "/bar/manifest-304-root-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/false, /*scope=*/"/");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-304-bar-override" ||
-               path == "/bar/manifest-304-bar-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/false, /*scope=*/"/bar/");
-      (*body) = kScopeManifestContents;
-    } else if (path == "/manifest-304-other-override" ||
-               path == "/bar/manifest-304-other-override") {
-      (*headers) = GetManifestHeaders(/*ok=*/false, /*scope=*/"/other/");
-      (*body) = kScopeManifestContents;
-    } else {
-      (*headers) =
-          std::string(not_found_headers, base::size(not_found_headers));
-      (*body) = "";
-    }
-  }
-};
-
-inline bool operator==(const AppCacheNamespace& lhs,
-                       const AppCacheNamespace& rhs) {
-  return lhs.type == rhs.type && lhs.namespace_url == rhs.namespace_url &&
-         lhs.target_url == rhs.target_url;
-}
-
-class MockFrontend : public blink::mojom::AppCacheFrontend {
- public:
-  MockFrontend()
-      : ignore_progress_events_(false),
-        verify_progress_events_(false),
-        last_progress_total_(-1),
-        last_progress_complete_(-1),
-        start_update_trigger_(
-            blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT),
-        update_(nullptr) {}
-
-  void CacheSelected(blink::mojom::AppCacheInfoPtr info) override {}
-
-  void EventRaised(blink::mojom::AppCacheEventID event_id) override {
-    raised_events_.push_back(event_id);
-
-    // Trigger additional updates if requested.
-    if (event_id == start_update_trigger_ && update_) {
-      for (AppCacheHost* host : update_hosts_) {
-        update_->StartUpdate(
-            host, (host ? host->pending_master_entry_url() : GURL()));
-      }
-      update_hosts_.clear();  // only trigger once
-    }
-  }
-
-  void ErrorEventRaised(
-      blink::mojom::AppCacheErrorDetailsPtr details) override {
-    error_message_ = details->message;
-    EventRaised(blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-  }
-
-  void ProgressEventRaised(const GURL& url,
-                           int32_t num_total,
-                           int32_t num_complete) override {
-    if (!ignore_progress_events_)
-      EventRaised(blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-
-    if (verify_progress_events_) {
-      EXPECT_GE(num_total, num_complete);
-      EXPECT_GE(num_complete, 0);
-
-      if (last_progress_total_ == -1) {
-        // Should start at zero.
-        EXPECT_EQ(0, num_complete);
-      } else {
-        // Total should be stable and complete should bump up by one at a time.
-        EXPECT_EQ(last_progress_total_, num_total);
-        EXPECT_EQ(last_progress_complete_ + 1, num_complete);
-      }
-
-      // Url should be valid for all except the 'final' event.
-      if (num_total == num_complete)
-        EXPECT_TRUE(url.is_empty());
-      else
-        EXPECT_TRUE(url.is_valid());
-
-      last_progress_total_ = num_total;
-      last_progress_complete_ = num_complete;
-    }
-  }
-
-  void LogMessage(blink::mojom::ConsoleMessageLevel log_level,
-                  const std::string& message) override {}
-
-  void SetSubresourceFactory(
-      mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory)
-      override {}
-
-  void AddExpectedEvent(blink::mojom::AppCacheEventID event_id) {
-    DCHECK(!ignore_progress_events_ ||
-           event_id != blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    expected_events_.push_back(event_id);
-  }
-
-  void SetIgnoreProgressEvents(bool ignore) {
-    // Some tests involve joining new hosts to an already running update job
-    // or intentionally failing. The timing and sequencing of the progress
-    // events generated by an update job are dependent on the behavior of
-    // an external HTTP server. For jobs that do not run fully till completion,
-    // due to either joining late or early exit, we skip monitoring the
-    // progress events to avoid flakiness.
-    ignore_progress_events_ = ignore;
-  }
-
-  void SetVerifyProgressEvents(bool verify) {
-    verify_progress_events_ = verify;
-  }
-
-  void TriggerAdditionalUpdates(blink::mojom::AppCacheEventID trigger_event,
-                                AppCacheUpdateJob* update) {
-    start_update_trigger_ = trigger_event;
-    update_ = update;
-  }
-
-  void AdditionalUpdateHost(AppCacheHost* host) {
-    update_hosts_.push_back(host);
-  }
-
-  using RaisedEvents = std::vector<blink::mojom::AppCacheEventID>;
-  RaisedEvents raised_events_;
-  std::string error_message_;
-
-  // Set the expected events if verification needs to happen asynchronously.
-  RaisedEvents expected_events_;
-  std::string expected_error_message_;
-
-  bool ignore_progress_events_;
-
-  bool verify_progress_events_;
-  int last_progress_total_;
-  int last_progress_complete_;
-
-  // Add ability for frontend to add master entries to an inprogress update.
-  blink::mojom::AppCacheEventID start_update_trigger_;
-  AppCacheUpdateJob* update_;
-  std::vector<AppCacheHost*> update_hosts_;
-};
-
-// Helper class to simulate a URL that returns retry or success.
-class RetryRequestTestJob {
- public:
-  enum RetryHeader {
-    NO_RETRY_AFTER,
-    NONZERO_RETRY_AFTER,
-    RETRY_AFTER_0,
-  };
-
-  static constexpr char kRetryUrl[] = "http://retry/";
-
-  // Call this at the start of each retry test.
-  static void Initialize(int num_retry_responses,
-                         RetryHeader header,
-                         int expected_requests) {
-    num_requests_ = 0;
-    num_retries_ = num_retry_responses;
-    retry_after_ = header;
-    expected_requests_ = expected_requests;
-  }
-
-  // Verifies results at end of test and resets counters.
-  static void Verify() {
-    EXPECT_EQ(expected_requests_, num_requests_);
-    num_requests_ = 0;
-    expected_requests_ = 0;
-  }
-
-  static void GetResponseForURL(const GURL& url,
-                                std::string* headers,
-                                std::string* data) {
-    ++num_requests_;
-    if (num_retries_ > 0 && IsRetryUrl(url)) {
-      --num_retries_;
-      *headers = RetryRequestTestJob::retry_headers();
-    } else {
-      *headers = RetryRequestTestJob::manifest_headers();
-    }
-    if (data)
-      *data = RetryRequestTestJob::data();
-  }
-
-  static bool IsRetryUrl(const GURL& url) { return url.spec() == kRetryUrl; }
-
- private:
-  static std::string retry_headers() {
-    const char no_retry_after[] =
-        "HTTP/1.1 503 BOO HOO\n"
-        "\n";
-    const char nonzero[] =
-        "HTTP/1.1 503 BOO HOO\n"
-        "Retry-After: 60\n"
-        "\n";
-    const char retry_after_0[] =
-        "HTTP/1.1 503 BOO HOO\n"
-        "Retry-After: 0\n"
-        "\n";
-
-    switch (retry_after_) {
-      case NO_RETRY_AFTER:
-        return std::string(no_retry_after, base::size(no_retry_after));
-      case NONZERO_RETRY_AFTER:
-        return std::string(nonzero, base::size(nonzero));
-      case RETRY_AFTER_0:
-      default:
-        return std::string(retry_after_0, base::size(retry_after_0));
-    }
-  }
-
-  static std::string manifest_headers() {
-    const char headers[] =
-        "HTTP/1.1 200 OK\n"
-        "Content-type: text/cache-manifest\n"
-        "\n";
-    return std::string(headers, base::size(headers));
-  }
-
-  static std::string data() {
-    return base::StrCat({"CACHE MANIFEST\r", kRetryUrl, "\r"});
-  }
-
-  static int num_requests_;
-  static int num_retries_;
-  static RetryHeader retry_after_;
-  static int expected_requests_;
-};
-
-// static
-constexpr char RetryRequestTestJob::kRetryUrl[];
-int RetryRequestTestJob::num_requests_ = 0;
-int RetryRequestTestJob::num_retries_;
-RetryRequestTestJob::RetryHeader RetryRequestTestJob::retry_after_;
-int RetryRequestTestJob::expected_requests_ = 0;
-
-// Helper class to check for certain HTTP headers.
-class HttpHeadersRequestTestJob {
- public:
-  HttpHeadersRequestTestJob() {
-    saw_if_modified_since_ = false;
-    saw_if_none_match_ = false;
-    headers_allowed_ = true;
-    saw_headers_ = false;
-    already_checked_ = false;
-  }
-
-  HttpHeadersRequestTestJob(const std::string& expect_if_modified_since,
-                            const std::string& expect_if_none_match,
-                            bool headers_allowed = true)
-      : expect_if_modified_since_(expect_if_modified_since),
-        saw_if_modified_since_(false),
-        expect_if_none_match_(expect_if_none_match),
-        saw_if_none_match_(false),
-        headers_allowed_(headers_allowed),
-        saw_headers_(false),
-        already_checked_(false),
-        verify_called_(false) {}
-
-  ~HttpHeadersRequestTestJob() { DCHECK(verify_called_); }
-
-  // Verifies results at end of test.
-  void Verify(const GURL& url) {
-    verify_called_ = true;
-    if (!expect_if_modified_since_.empty())
-      EXPECT_TRUE(saw_if_modified_since_) << "URL " << url.spec() << " failed";
-    if (!expect_if_none_match_.empty())
-      EXPECT_TRUE(saw_if_none_match_) << "URL " << url.spec() << " failed";
-    if (!headers_allowed_)
-      EXPECT_FALSE(saw_headers_) << "URL " << url.spec() << " failed";
-  }
-
-  void ValidateExtraHeaders(const net::HttpRequestHeaders& extra_headers) {
-    if (already_checked_)
-      return;
-
-    already_checked_ = true;  // only check once for a test
-
-    std::string header_value;
-
-    if (extra_headers.GetHeader(net::HttpRequestHeaders::kIfModifiedSince,
-                                &header_value)) {
-      saw_headers_ = true;
-      saw_if_modified_since_ = header_value == expect_if_modified_since_;
-    }
-
-    if (extra_headers.GetHeader(net::HttpRequestHeaders::kIfNoneMatch,
-                                &header_value)) {
-      saw_headers_ = true;
-      saw_if_none_match_ = header_value == expect_if_none_match_;
-    }
-  }
-
- private:
-  std::string expect_if_modified_since_;
-  bool saw_if_modified_since_;
-  std::string expect_if_none_match_;
-  bool saw_if_none_match_;
-  bool headers_allowed_;
-  bool saw_headers_;
-  bool already_checked_;
-  bool verify_called_;
-};
-
-class AppCacheUpdateJobTest : public testing::Test,
-                              public AppCacheGroup::UpdateObserver {
- public:
-  AppCacheUpdateJobTest()
-      : do_checks_after_update_finished_(false),
-        expect_group_obsolete_(false),
-        expect_group_has_cache_(false),
-        expect_group_is_being_deleted_(false),
-        expect_evictable_error_(false),
-        expect_eviction_(false),
-        expect_old_cache_(nullptr),
-        expect_newest_cache_(nullptr),
-        expect_non_null_update_time_(false),
-        tested_manifest_(NONE),
-        tested_manifest_path_override_(nullptr),
-        interceptor_(
-            base::BindRepeating(&AppCacheUpdateJobTest::InterceptRequest,
-                                base::Unretained(this))),
-        process_id_(123) {
-    appcache_require_origin_trial_feature_.InitAndDisableFeature(
-        blink::features::kAppCacheRequireOriginTrial);
-    appcache_disable_corruption_feature_.InitAndDisableFeature(
-        kAppCacheCorruptionRecoveryFeature);
-  }
-
-  // TODO(ananta/michaeln): Remove dependencies on URLRequest based
-  // classes by refactoring the response headers/data into a common class.
-  bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) {
-    const auto& url_request = params->url_request;
-    if (url_request.url.host() == "failme" ||
-        url_request.url.host() == "testme") {
-      params->client->OnComplete(network::URLLoaderCompletionStatus(-100));
-      return true;
-    }
-
-    auto it = http_headers_request_test_jobs_.find(url_request.url);
-    if (it != http_headers_request_test_jobs_.end())
-      it->second->ValidateExtraHeaders(url_request.headers);
-
-    // Copy the URL so we can optionally override it under certain conditions.
-    GURL requested_url = url_request.url;
-
-    // If "files/maybemodified" is requested without a conditional header,
-    // treat the request as if it's a request for "files/modified".  The
-    // result will be a 200 OK response (rather than maybemodified's normal
-    // 304 response).
-    if (requested_url.path() == "/files/maybemodified" &&
-        !url_request.headers.HasHeader("If-Modified-Since")) {
-      requested_url = GURL("http://mockhost/files/modified");
-    }
-
-    std::string headers;
-    std::string body;
-    if (RetryRequestTestJob::IsRetryUrl(requested_url)) {
-      RetryRequestTestJob::GetResponseForURL(requested_url, &headers, &body);
-    } else {
-      MockHttpServer::GetMockResponse(requested_url.path(), &headers, &body);
-    }
-
-    net::HttpResponseInfo info;
-    info.headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        net::HttpUtil::AssembleRawHeaders(headers));
-
-    auto response = network::mojom::URLResponseHead::New();
-    response->headers = info.headers;
-    response->headers->GetMimeType(&response->mime_type);
-
-    // Provide valid request and response times to
-    // UpdateUrlLoaderRequest.  It's still up to that class's
-    // |OnReceiveResponse| to capture these values in the net::HttpResponseInfo.
-    response->request_time = base::Time::Now();
-    response->response_time = base::Time::Now();
-
-    params->client->OnReceiveResponse(std::move(response));
-
-    mojo::ScopedDataPipeProducerHandle producer_handle;
-    mojo::ScopedDataPipeConsumerHandle consumer_handle;
-    mojo::CreateDataPipe(nullptr, producer_handle, consumer_handle);
-
-    uint32_t bytes_written = body.size();
-    producer_handle->WriteData(body.data(), &bytes_written,
-                               MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
-    params->client->OnStartLoadingResponseBody(std::move(consumer_handle));
-    return true;
-  }
-
-  void SetUp() override {
-    browser_context_ = std::make_unique<content::TestBrowserContext>();
-    weak_partition_factory_ =
-        std::make_unique<base::WeakPtrFactory<StoragePartitionImpl>>(
-            static_cast<StoragePartitionImpl*>(
-                browser_context_->GetDefaultStoragePartition()));
-
-    ChildProcessSecurityPolicyImpl::GetInstance()->AddForTesting(
-        process_id_, browser_context_.get());
-  }
-
-  void TearDown() override {
-    weak_partition_factory_.reset();
-    browser_context_.reset();
-
-    ChildProcessSecurityPolicyImpl::GetInstance()->Remove(process_id_);
-  }
-  // Use a separate IO thread to run a test. Thread will be destroyed
-  // when it goes out of scope.
-  template <class Method>
-  void RunTestOnUIThread(Method method) {
-    base::RunLoop run_loop;
-    test_completed_cb_ = run_loop.QuitClosure();
-    GetUIThreadTaskRunner({})->PostTask(
-        FROM_HERE, base::BindOnce(method, base::Unretained(this)));
-    run_loop.Run();
-  }
-
-  void StartCacheAttemptTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://failme"),
-        service_->storage()->NewGroupId());
-
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend mock_frontend;
-    const int kMockProcessId1 = 1;
-    AppCacheHost host(
-        /*host_id=*/base::UnguessableToken::Create(), kMockProcessId1,
-        /*render_frame_id=*/1,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            kMockProcessId1),
-        mojo::NullRemote(), service_.get());
-    host.set_frontend_for_testing(&mock_frontend);
-
-    update->StartUpdate(&host, GURL());
-
-    // Verify state.
-    EXPECT_EQ(AppCacheUpdateJob::CACHE_ATTEMPT, update->update_type_);
-    EXPECT_EQ(AppCacheUpdateJobState::FETCH_MANIFEST, update->internal_state_);
-    EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
-    EXPECT_TRUE(update->doing_full_update_check_);
-
-    // Verify notifications.
-    MockFrontend::RaisedEvents& events = mock_frontend.raised_events_;
-    ASSERT_EQ(1u, events.size());
-    EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT,
-              events[0]);
-
-    // Abort as we're not testing actual URL fetches in this test.
-    delete update;
-    UpdateFinished();
-  }
-
-  void StartUpgradeAttemptTest() {
-    {
-      MakeService();
-      group_ = base::MakeRefCounted<AppCacheGroup>(
-          service_->storage(), GURL("http://failme"),
-          service_->storage()->NewGroupId());
-
-      // Give the group some existing caches.
-      AppCache* cache1 = MakeCacheForGroup(1, 111);
-      AppCache* cache2 = MakeCacheForGroup(2, 222);
-
-      // Associate some hosts with caches in the group.
-      MockFrontend mock_frontend1;
-      MockFrontend mock_frontend2;
-      MockFrontend mock_frontend3;
-      MockFrontend mock_frontend4;
-
-      const int kMockProcessId1 = 1;
-      const int kMockProcessId2 = 2;
-      const int kMockProcessId3 = 3;
-      const int kMockProcessId4 = 4;
-      AppCacheHost host1(
-          /*host_id=*/base::UnguessableToken::Create(), kMockProcessId1,
-          /*render_frame_id=*/1,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId1),
-          mojo::NullRemote(), service_.get());
-      host1.set_frontend_for_testing(&mock_frontend1);
-      host1.AssociateCompleteCache(cache1);
-
-      AppCacheHost host2(
-          /*host_id=*/base::UnguessableToken::Create(), kMockProcessId2,
-          /*render_frame_id=*/2,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId2),
-          mojo::NullRemote(), service_.get());
-      host2.set_frontend_for_testing(&mock_frontend2);
-      host2.AssociateCompleteCache(cache2);
-
-      AppCacheHost host3(
-          /*host_id=*/base::UnguessableToken::Create(), kMockProcessId3,
-          /*render_frame_id=*/3,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId3),
-          mojo::NullRemote(), service_.get());
-      host3.set_frontend_for_testing(&mock_frontend3);
-      host3.AssociateCompleteCache(cache1);
-
-      AppCacheHost host4(
-          /*host_id=*/base::UnguessableToken::Create(), kMockProcessId4,
-          /*render_frame_id=*/4,
-          ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-              kMockProcessId4),
-          mojo::NullRemote(), service_.get());
-      host4.set_frontend_for_testing(&mock_frontend4);
-
-      AppCacheUpdateJob* update =
-          new AppCacheUpdateJob(service_.get(), group_.get());
-      group_->update_job_ = update;
-      update->StartUpdate(&host4, GURL());
-
-      // Verify state after starting an update.
-      EXPECT_EQ(AppCacheUpdateJob::UPGRADE_ATTEMPT, update->update_type_);
-      EXPECT_EQ(AppCacheUpdateJobState::FETCH_MANIFEST,
-                update->internal_state_);
-      EXPECT_EQ(AppCacheGroup::CHECKING, group_->update_status());
-      EXPECT_FALSE(update->doing_full_update_check_);
-
-      // Verify notifications.
-      MockFrontend::RaisedEvents events = mock_frontend1.raised_events_;
-      ASSERT_EQ(1u, events.size());
-      EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT,
-                events[0]);
-
-      events = mock_frontend2.raised_events_;
-      ASSERT_EQ(1u, events.size());
-      EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT,
-                events[0]);
-
-      events = mock_frontend3.raised_events_;
-      ASSERT_EQ(1u, events.size());
-      EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT,
-                events[0]);
-
-      events = mock_frontend4.raised_events_;
-      EXPECT_TRUE(events.empty());
-
-      // Abort as we're not testing actual URL fetches in this test.
-      delete update;
-    }
-    UpdateFinished();
-  }
-
-  void CacheAttemptFetchManifestFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://failme"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeFetchManifestFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/servererror"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    group_->set_last_full_update_check_time(base::Time::Now() -
-                                            kFullUpdateInterval - kOneHour);
-    update->StartUpdate(nullptr, GURL());
-    EXPECT_TRUE(update->doing_full_update_check_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_evictable_error_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    expect_full_update_time_equal_to_ = group_->last_full_update_check_time();
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void ManifestRedirectTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://testme"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // redirect is like a failed request
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void ManifestMissingMimeTypeTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/missing-mime-manifest"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    frontend->SetVerifyProgressEvents(true);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = EMPTY_MANIFEST;
-    tested_manifest_path_override_ = "files/missing-mime-manifest";
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void ManifestNotFoundTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = true;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void ManifestGoneFetchTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/gone"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void ManifestGoneUpgradeTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/gone"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    host->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = true;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_OBSOLETE_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void CacheAttemptNotModifiedTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // treated like cache failure
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeNotModifiedTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    group_->set_last_full_update_check_time(base::Time::Now() -
-                                            kFullUpdateInterval - kOneHour);
-    group_->set_first_evictable_error_time(base::Time::Now());
-    update->StartUpdate(nullptr, GURL());
-    EXPECT_TRUE(update->doing_full_update_check_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;     // newest cache unaffected by update
-    expect_evictable_error_ = false;  // should be reset
-    expect_full_update_time_newer_than_ = group_->last_full_update_check_time();
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeNotModifiedVersion1Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    cache->set_manifest_parser_version(1);
-    EXPECT_EQ(cache->token_expires(), base::Time());
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_path_override_ = "files/notmodified";
-    tested_manifest_ = MANIFEST1;
-    expect_token_expires_ = kTestOriginTrialTokenExpiry;
-
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed the response_info working set with canned data so that an existing
-    // manifest is reused by the update job.
-    const char kData[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    const std::string kRawHeaders(kData, base::size(kData));
-    MakeAppCacheResponseInfo(group_->manifest_url(),
-                             response_writer_->response_id(), kRawHeaders);
-
-    // Last data parsed pretends to be version 1, and doesn't know about
-    // the origin trial (verified above).  Even with a 304, this should
-    // refresh the token expires field.
-    const std::string seed_data(kManifest1OriginTrialContents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeManifestDataChangedScopeUnchangedTest() {
-    MakeService();
-    // URL path /files/manifest2-with-root-override has a cached scope of "/".
-    // The path has a scope override of "/", so the fetched scope will be "/"
-    // and no scope change will occur.
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest2-with-root-override"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST2_WITH_ROOT_SCOPE;
-
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with manifest1 contents.  The result should be that the
-    // manifest2 fetch results in different byte-for-byte data.
-    const std::string seed_data(kManifest1Contents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeManifestDataChangedScopeChangedTest() {
-    MakeService();
-    // URL path /files/manifest2 has a cached scope of "/".  The path has no
-    // scope override, so the fetched scope will be "/files/" and a scope change
-    // will occur.
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest2"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST2_WITH_FILES_SCOPE;
-
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with manifest1 contents.  The result should be that the
-    // manifest2 fetch results in different byte-for-byte data.
-    const std::string seed_data(kManifest1Contents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeManifestDataUnchangedScopeUnchangedTest() {
-    MakeService();
-    // URL path /files/manifest2-with-root-override has a cached scope of "/".
-    // The path has a scope override of "/", so the fetched scope will be "/"
-    // and no scope change will occur.
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest2-with-root-override"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    // Seed storage with expected manifest data.
-    const std::string seed_data(kManifest2Contents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeManifestDataUnchangedScopeChangedTest() {
-    MakeService();
-    // URL path /files/manifest2 has a cached scope of "/".  The path has no
-    // scope override, so the fetched scope will be "/files/" and a scope change
-    // will occur.
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest2"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST2_WITH_FILES_SCOPE;
-
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected manifest data.
-    const std::string seed_data(kManifest2Contents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  // See http://code.google.com/p/chromium/issues/detail?id=95101
-  void Bug95101Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a malformed cache with a missing manifest entry.
-    GURL wrong_manifest_url =
-        MockHttpServer::GetMockUrl("files/missing-mime-manifest");
-    AppCache* cache = MakeCacheForGroup(1, wrong_manifest_url, 111);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_is_being_deleted_ = true;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-    frontend->expected_error_message_ =
-        "Manifest entry not found in existing cache";
-    WaitForUpdateToFinish();
-  }
-
-  void StartUpdateAfterSeedingStorageData(int result) {
-    ASSERT_GT(result, 0);
-    response_writer_.reset();
-
-    AppCacheUpdateJob* update = group_->update_job_;
-    update->StartUpdate(nullptr, GURL());
-
-    WaitForUpdateToFinish();
-  }
-
-  void BasicCacheAttemptSuccessTest() {
-    GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1");
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    ASSERT_TRUE(group_->last_full_update_check_time().is_null());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_full_update_time_newer_than_ = base::Time::Now() - kOneHour;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  // Tests that 200 OK responses with varying scopes result in the expected
-  // AppCache data stored in the cache.
-  void ScopeManifestRootWithNoOverrideTest() {
-    ScopeTest("manifest-no-override", SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifestBarWithNoOverrideTest() {
-    ScopeTest("bar/manifest-no-override", SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifestRootWithRootOverrideTest() {
-    ScopeTest("manifest-root-override", SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifestBarWithRootOverrideTest() {
-    ScopeTest("bar/manifest-root-override", SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifestRootWithBarOverrideTest() {
-    ScopeTest("manifest-bar-override", SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifestBarWithBarOverrideTest() {
-    ScopeTest("bar/manifest-bar-override", SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifestRootWithOtherOverrideTest() {
-    ScopeTest("manifest-other-override", SCOPE_MANIFEST_OTHER);
-  }
-
-  void ScopeManifestBarWithOtherOverrideTest() {
-    ScopeTest("bar/manifest-other-override", SCOPE_MANIFEST_OTHER);
-  }
-
-  // Tests that 304 NOT MODIFIED responses with varying scopes result in the
-  // expected AppCache data stored in the cache.
-  void ScopeManifest304RootWithNoOverrideTest() {
-    Scope304Test("manifest-304-no-override", /*previous_scope=*/"/bar/",
-                 SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifest304BarWithNoOverrideTest() {
-    Scope304Test("bar/manifest-304-no-override", /*previous_scope=*/"/baz/",
-                 SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifest304RootWithRootOverrideTest() {
-    Scope304Test("manifest-304-root-override", /*previous_scope=*/"/bar/",
-                 SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifest304BarWithRootOverrideTest() {
-    Scope304Test("bar/manifest-304-root-override", /*previous_scope=*/"/baz/",
-                 SCOPE_MANIFEST_ROOT);
-  }
-
-  void ScopeManifest304RootWithBarOverrideTest() {
-    Scope304Test("manifest-304-bar-override", /*previous_scope=*/"/baz/",
-                 SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifest304BarWithBarOverrideTest() {
-    Scope304Test("bar/manifest-304-bar-override", /*previous_scope=*/"/baz/",
-                 SCOPE_MANIFEST_BAR);
-  }
-
-  void ScopeManifest304RootWithOtherOverrideTest() {
-    Scope304Test("manifest-304-other-override", /*previous_scope=*/"/bar/",
-                 SCOPE_MANIFEST_OTHER);
-  }
-
-  void ScopeManifest304BarWithOtherOverrideTest() {
-    Scope304Test("bar/manifest-304-other-override", /*previous_scope=*/"/baz/",
-                 SCOPE_MANIFEST_OTHER);
-  }
-
-  void DownloadInterceptEntriesTest() {
-    // Ensures we download intercept entries too.
-    GURL manifest_url =
-        MockHttpServer::GetMockUrl("files/manifest-with-intercept");
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST_WITH_INTERCEPT;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void BasicUpgradeSuccessTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-    frontend1->SetVerifyProgressEvents(true);
-    frontend2->SetVerifyProgressEvents(true);
-    group_->set_last_full_update_check_time(base::Time::Now() -
-                                            kFullUpdateInterval - kOneHour);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    expect_full_update_time_newer_than_ = group_->last_full_update_check_time();
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected manifest data different from manifest1.
-    const std::string seed_data("different");
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeLoadFromNewestCacheTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Give the newest cache an entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                  response_writer_->response_id()));
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
-        MockHttpServer::GetMockUrl("files/explicit1"),
-        response_writer_->response_id()));
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected http response info for entry. Allow reuse.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Cache-Control: max-age=8675309\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->request_time = base::Time::Now();
-    response_info->response_time = base::Time::Now();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeNoLoadFromNewestCacheTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Give the newest cache an entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                  response_writer_->response_id()));
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected http response info for entry. Do NOT
-    // allow reuse by setting an expires header in the past.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Expires: Thu, 01 Dec 1994 16:00:00 GMT\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->request_time = base::Time::Now();
-    response_info->response_time = base::Time::Now();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeLoadFromNewestCacheVaryHeaderTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Give the newest cache an entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                  response_writer_->response_id()));
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected http response info for entry: a vary header.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Cache-Control: max-age=8675309\0"
-        "Vary: blah\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->request_time = base::Time::Now();
-    response_info->response_time = base::Time::Now();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeLoadFromNewestCacheReuseVaryHeaderTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Give the newest cache an entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT,
-                                  response_writer_->response_id()));
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
-        MockHttpServer::GetMockUrl("files/explicit1"),
-        response_writer_->response_id()));
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected http response info for an entry
-    // with a vary header for which we allow reuse.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Cache-Control: max-age=8675309\0"
-        "Vary: origin, accept-encoding\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->request_time = base::Time::Now();
-    response_info->response_time = base::Time::Now();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void UpgradeSuccessMergedTypesTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest-merged-types"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Give the newest cache a master entry that is also one of the explicit
-    // entries in the manifest.
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit1"),
-                    AppCacheEntry(AppCacheEntry::MASTER, 111));
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST_MERGED_TYPES;
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // explicit1
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // manifest
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void CacheAttemptFailUrlFetchTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest-with-404"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // 404 explicit url is cache failure
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeFailUrlFetchTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest-fb-404"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 99);
-    group_->set_first_evictable_error_time(
-        base::Time::Now() - kMaxEvictableErrorDuration - kOneHour);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    frontend1->SetIgnoreProgressEvents(true);
-    frontend2->SetIgnoreProgressEvents(true);
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffectd by failed update
-    expect_eviction_ = true;
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeFailMasterUrlFetchTest() {
-    tested_manifest_path_override_ = "files/manifest1-with-notmodified";
-
-    MakeService();
-    const GURL kManifestUrl =
-        MockHttpServer::GetMockUrl(tested_manifest_path_override_);
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), kManifestUrl, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 25);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Give the newest cache some existing entries; one will fail with a 404.
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/notfound"),
-                    AppCacheEntry(AppCacheEntry::MASTER, 222));
-    cache->AddEntry(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER | AppCacheEntry::FOREIGN, 333));
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/servererror"),
-                    AppCacheEntry(AppCacheEntry::MASTER, 444));
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/notmodified"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT, 555));
-
-    // Seed the response_info working set with canned data for
-    // files/servererror and for files/notmodified to test that the
-    // existing entries for those resource are reused by the update job.
-    const char kData[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    const std::string kRawHeaders(kData, base::size(kData));
-    MakeAppCacheResponseInfo(kManifestUrl, 444, kRawHeaders);
-    MakeAppCacheResponseInfo(kManifestUrl, 555, kRawHeaders);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER)));  // foreign flag is dropped
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/servererror"),
-        AppCacheEntry(AppCacheEntry::MASTER)));
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/notmodified"),
-        AppCacheEntry(AppCacheEntry::EXPLICIT)));
-    expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
-        MockHttpServer::GetMockUrl("files/servererror"), 444));  // copied
-    expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
-        MockHttpServer::GetMockUrl("files/notmodified"), 555));  // copied
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // explicit1
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // fallback1a
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // notfound
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // explicit2
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // servererror
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // notmodified
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // explicit1
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // fallback1a
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // notfound
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // explicit2
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // servererror
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // notmodified
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void EmptyManifestTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/empty-manifest"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 33);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    frontend1->SetVerifyProgressEvents(true);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = EMPTY_MANIFEST;
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void EmptyFileTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/empty-file-manifest"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 22);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-    frontend->SetVerifyProgressEvents(true);
-
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = EMPTY_FILE_MANIFEST;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void RetryRetryAfterTest() {
-    // Set some large number of times to return retry.
-    // Expect 1 manifest fetch and 3 retries.
-    RetryRequestTestJob::Initialize(5, RetryRequestTestJob::RETRY_AFTER_0, 4);
-    RetryRequestTest(false);
-  }
-
-  void RetryNoRetryAfterTest() {
-    // Set some large number of times to return retry.
-    // Expect 1 manifest fetch and 0 retries.
-    RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NO_RETRY_AFTER, 1);
-    RetryRequestTest(false);
-  }
-
-  void RetryNonzeroRetryAfterTest() {
-    // Set some large number of times to return retry.
-    // Expect 1 request and 0 retry attempts.
-    RetryRequestTestJob::Initialize(5, RetryRequestTestJob::NONZERO_RETRY_AFTER,
-                                    1);
-    RetryRequestTest(false);
-  }
-
-  void RetrySuccessTest() {
-    // Set 2 as the retry limit (does not exceed the max).
-    // Expect 1 manifest fetch, 2 retries, 1 url fetch, 1 manifest refetch.
-    RetryRequestTestJob::Initialize(2, RetryRequestTestJob::RETRY_AFTER_0, 5);
-    RetryRequestTest(true);
-  }
-
-  void RetryUrlTest() {
-    // Set 1 as the retry limit (does not exceed the max).
-    // Expect 1 manifest fetch, 1 url fetch, 1 url retry, 1 manifest refetch.
-    RetryRequestTestJob::Initialize(1, RetryRequestTestJob::RETRY_AFTER_0, 4);
-    RetryRequestTest(true);
-  }
-
-  void FailStoreNewestCacheTest() {
-    MakeService();
-    MockAppCacheStorage* storage =
-        static_cast<MockAppCacheStorage*>(service_->storage());
-    storage->SimulateStoreGroupAndNewestCacheFailure();
-
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // storage failed
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeFailStoreNewestCacheTest() {
-    MakeService();
-    MockAppCacheStorage* storage =
-        static_cast<MockAppCacheStorage*>(service_->storage());
-    storage->SimulateStoreGroupAndNewestCacheFailure();
-
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 11);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // unchanged
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryFailStoreNewestCacheTest() {
-    MakeService();
-    MockAppCacheStorage* storage =
-        static_cast<MockAppCacheStorage*>(service_->storage());
-    storage->SimulateStoreGroupAndNewestCacheFailure();
-
-    const GURL kManifestUrl = MockHttpServer::GetMockUrl("files/notmodified");
-    const int64_t kManifestResponseId = 11;
-
-    // Seed the response_info working set with canned data for
-    // files/servererror and for files/notmodified to test that the
-    // existing entries for those resource are reused by the update job.
-    const char kData[] =
-        "HTTP/1.1 200 OK\0"
-        "Content-type: text/cache-manifest\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    const std::string kRawHeaders(kData, base::size(kData));
-    MakeAppCacheResponseInfo(kManifestUrl, kManifestResponseId, kRawHeaders);
-
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), kManifestUrl, service_->storage()->NewGroupId());
-    scoped_refptr<AppCache> cache(MakeCacheForGroup(
-        service_->storage()->NewCacheId(), kManifestResponseId));
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->SetSiteForCookiesForTesting(
-        net::SiteForCookies::FromUrl(kManifestUrl));
-    host->SelectCache(MockHttpServer::GetMockUrl("files/empty1"),
-                      blink::mojom::kAppCacheNoCacheId, kManifestUrl);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    tested_manifest_ = EMPTY_MANIFEST;
-    tested_manifest_path_override_ = "files/notmodified";
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache.get();  // unchanged
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-    frontend->expected_error_message_ = "Failed to commit new cache to storage";
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeFailMakeGroupObsoleteTest() {
-    MakeService();
-    MockAppCacheStorage* storage =
-        static_cast<MockAppCacheStorage*>(service_->storage());
-    storage->SimulateMakeGroupObsoleteFailure();
-
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryFetchManifestFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(service_->storage(),
-                                                 GURL("http://failme"), 111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->new_master_entry_url_ = GURL("http://failme/blah");
-    update->StartUpdate(host, host->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryBadManifestTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/bad-manifest"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
-    update->StartUpdate(host, host->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryManifestNotFoundTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/nosuchfile"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/blah");
-
-    update->StartUpdate(host, host->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryFailUrlFetchTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest-fb-404"), 111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    frontend->SetIgnoreProgressEvents(true);
-    AppCacheHost* host = MakeHost(frontend);
-    host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/explicit1");
-
-    update->StartUpdate(host, host->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // 404 fallback url is cache failure
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryAllFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend1 = MakeMockFrontend();
-    frontend1->SetIgnoreProgressEvents(true);
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-    update->StartUpdate(host1, host1->new_master_entry_url_);
-
-    MockFrontend* frontend2 = MakeMockFrontend();
-    frontend2->SetIgnoreProgressEvents(true);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/servererror");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;  // all pending masters failed
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeMasterEntryAllFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    MockFrontend* frontend2 = MakeMockFrontend();
-    frontend2->SetIgnoreProgressEvents(true);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    MockFrontend* frontend3 = MakeMockFrontend();
-    frontend3->SetIgnoreProgressEvents(true);
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/servererror");
-    update->StartUpdate(host3, host3->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntrySomeFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend1 = MakeMockFrontend();
-    frontend1->SetIgnoreProgressEvents(true);
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-    update->StartUpdate(host1, host1->new_master_entry_url_);
-
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;  // as long as one pending master succeeds
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER)));
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void UpgradeMasterEntrySomeFailTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    MockFrontend* frontend2 = MakeMockFrontend();
-    frontend2->SetIgnoreProgressEvents(true);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    MockFrontend* frontend3 = MakeMockFrontend();
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-    update->StartUpdate(host3, host3->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER)));
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void MasterEntryNoUpdateTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    // Give cache an existing entry that can also be fetched.
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
-
-    // Reset the update time to null so we can verify it gets
-    // modified in this test case by the UpdateJob.
-    cache->set_update_time(base::Time());
-
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit1");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    MockFrontend* frontend3 = MakeMockFrontend();
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-    update->StartUpdate(host3, host3->new_master_entry_url_);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache still the same cache
-    expect_non_null_update_time_ = true;
-    tested_manifest_ = PENDING_MASTER_NO_UPDATE;
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void StartUpdateMidCacheAttemptTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-    update->StartUpdate(host1, host1->new_master_entry_url_);
-
-    // Set up additional updates to be started while update is in progress.
-    MockFrontend* frontend2 = MakeMockFrontend();
-    frontend2->SetIgnoreProgressEvents(true);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-
-    MockFrontend* frontend3 = MakeMockFrontend();
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit1");
-
-    MockFrontend* frontend4 = MakeMockFrontend();
-    AppCacheHost* host4 = MakeHost(frontend4);
-    host4->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-
-    MockFrontend* frontend5 = MakeMockFrontend();
-    AppCacheHost* host5 = MakeHost(frontend5);  // no master entry url
-
-    frontend1->TriggerAdditionalUpdates(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT, update);
-    frontend1->AdditionalUpdateHost(host2);    // fetch will fail
-    frontend1->AdditionalUpdateHost(host3);    // same as an explicit entry
-    frontend1->AdditionalUpdateHost(host4);    // same as another master entry
-    frontend1->AdditionalUpdateHost(nullptr);  // no host
-    frontend1->AdditionalUpdateHost(host5);    // no master entry url
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER)));
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT);
-
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT);
-
-    // Host 5 is not associated with cache so no progress/cached events.
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void StartUpdateMidNoUpdateTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/notmodified"),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(1, 111);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    // Give cache an existing entry.
-    cache->AddEntry(MockHttpServer::GetMockUrl("files/explicit2"),
-                    AppCacheEntry(AppCacheEntry::EXPLICIT, 222));
-
-    // Start update with a pending master entry that will fail to give us an
-    // event to trigger other updates.
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/nosuchfile");
-    update->StartUpdate(host2, host2->new_master_entry_url_);
-
-    // Set up additional updates to be started while update is in progress.
-    MockFrontend* frontend3 = MakeMockFrontend();
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit1");
-
-    MockFrontend* frontend4 = MakeMockFrontend();
-    AppCacheHost* host4 = MakeHost(frontend4);  // no master entry url
-
-    MockFrontend* frontend5 = MakeMockFrontend();
-    AppCacheHost* host5 = MakeHost(frontend5);
-    host5->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");  // existing entry
-
-    MockFrontend* frontend6 = MakeMockFrontend();
-    AppCacheHost* host6 = MakeHost(frontend6);
-    host6->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit1");
-
-    frontend2->TriggerAdditionalUpdates(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT, update);
-    frontend2->AdditionalUpdateHost(host3);
-    frontend2->AdditionalUpdateHost(nullptr);  // no host
-    frontend2->AdditionalUpdateHost(host4);    // no master entry url
-    frontend2->AdditionalUpdateHost(host5);    // same as existing cache entry
-    frontend2->AdditionalUpdateHost(host6);    // same as another master entry
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_newest_cache_ = cache;  // newest cache unaffected by update
-    tested_manifest_ = PENDING_MASTER_NO_UPDATE;
-    // prior associated host
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_ERROR_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    // unassociated w/cache
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    frontend6->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend6->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_NO_UPDATE_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void StartUpdateMidDownloadTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), 42);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    update->StartUpdate(nullptr, GURL());
-
-    // Set up additional updates to be started while update is in progress.
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host2->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit1");
-
-    MockFrontend* frontend3 = MakeMockFrontend();
-    AppCacheHost* host3 = MakeHost(frontend3);
-    host3->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-
-    MockFrontend* frontend4 = MakeMockFrontend();
-    AppCacheHost* host4 = MakeHost(frontend4);  // no master entry url
-
-    MockFrontend* frontend5 = MakeMockFrontend();
-    AppCacheHost* host5 = MakeHost(frontend5);
-    host5->new_master_entry_url_ =
-        MockHttpServer::GetMockUrl("files/explicit2");
-
-    frontend1->TriggerAdditionalUpdates(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT, update);
-    frontend1->AdditionalUpdateHost(host2);    // same as entry in manifest
-    frontend1->AdditionalUpdateHost(nullptr);  // no host
-    frontend1->AdditionalUpdateHost(host3);    // new master entry
-    frontend1->AdditionalUpdateHost(host4);    // no master entry url
-    frontend1->AdditionalUpdateHost(host5);    // same as another master entry
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        MockHttpServer::GetMockUrl("files/explicit2"),
-        AppCacheEntry(AppCacheEntry::MASTER)));
-    // prior associated host
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend3->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // unassociated w/cache
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend4->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend5->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void QueueMasterEntryTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Pretend update job has been running and is about to terminate.
-    group_->update_status_ = AppCacheGroup::DOWNLOADING;
-    update->internal_state_ = AppCacheUpdateJobState::REFETCH_MANIFEST;
-    EXPECT_TRUE(update->IsTerminating());
-
-    // Start an update. Should be queued.
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->new_master_entry_url_ = MockHttpServer::GetMockUrl("files/explicit2");
-    update->StartUpdate(host, host->new_master_entry_url_);
-    EXPECT_TRUE(update->pending_master_entries_.empty());
-    EXPECT_FALSE(group_->queued_updates_.empty());
-
-    // Delete update, causing it to finish, which should trigger a new update
-    // for the queued host and master entry after a delay.
-    delete update;
-    EXPECT_FALSE(group_->restart_update_task_.IsCancelled());
-
-    // Set up checks for when queued update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST1;
-    expect_extra_entries_.insert(AppCache::EntryMap::value_type(
-        host->new_master_entry_url_, AppCacheEntry(AppCacheEntry::MASTER)));
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CACHED_EVENT);
-
-    // Group status will be blink::mojom::AppCacheStatus::APPCACHE_STATUS_IDLE
-    // so cannot call WaitForUpdateToFinish.
-    group_->AddUpdateObserver(this);
-  }
-
-  void VerifyHeadersAndDeleteUpdate(AppCacheUpdateJob* update) {
-    for (const auto& kvp : http_headers_request_test_jobs_)
-      kvp.second->Verify(kvp.first);
-    delete update;
-  }
-
-  void IfModifiedSinceTestCache() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://headertest"), 111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // First test against a cache attempt. Will start manifest fetch
-    // synchronously.
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), std::string()));
-    MockFrontend mock_frontend;
-    const int kMockProcessId1 = 1;
-    AppCacheHost host(
-        /*host_id=*/base::UnguessableToken::Create(), kMockProcessId1,
-        /*render_frame_id=*/1,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            kMockProcessId1),
-        mojo::NullRemote(), service_.get());
-    host.set_frontend_for_testing(&mock_frontend);
-    update->StartUpdate(&host, GURL());
-
-    // We need to wait for the URL load requests to make it to the
-    // URLLoaderInterceptor.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                       base::Unretained(this), update));
-
-    TriggerTestComplete();
-  }
-
-  void IfModifiedTestRefetch() {
-    // Now simulate a refetch manifest request. Will start fetch request
-    // synchronously.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "\0";
-    auto response_info = std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(data, base::size(data)));
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://headertest"), 111);
-
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), std::string()));
-
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-    group_->update_status_ = AppCacheGroup::DOWNLOADING;
-    update->manifest_response_info_ = std::move(response_info);
-    update->internal_state_ = AppCacheUpdateJobState::REFETCH_MANIFEST;
-    update->RefetchManifest();
-
-    // We need to wait for the URL load requests to make it to the
-    // URLLoaderInterceptor.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                       base::Unretained(this), update));
-
-    TriggerTestComplete();
-  }
-
-  void IfModifiedTestLastModified() {
-    // Change the headers to include a Last-Modified header. Manifest refetch
-    // should include If-Modified-Since header.
-    const char data2[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    auto response_info = std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(data2, base::size(data2)));
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://headertest"), 111);
-
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(),
-        std::make_unique<HttpHeadersRequestTestJob>(
-            "Sat, 29 Oct 1994 19:43:31 GMT", std::string()));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-    group_->update_status_ = AppCacheGroup::DOWNLOADING;
-    update->manifest_response_info_ = std::move(response_info);
-    update->internal_state_ = AppCacheUpdateJobState::REFETCH_MANIFEST;
-    update->RefetchManifest();
-
-    // We need to wait for the URL load requests to make it to the
-    // URLLoaderInterceptor.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                       base::Unretained(this), update));
-
-    TriggerTestComplete();
-  }
-
-  // AppCaches built with manifest parser version 0 should update without
-  // conditional request headers to force the server to send a 200 response
-  // back to the client rather than 304.  This test ensures that, when the cache
-  // has a response info with cached Last-Modified headers, the request does not
-  // include an If-Modified-Since conditioanl header.
-  void IfModifiedSinceUpgradeParserVersion0Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), std::string(),
-                                    /*headers_allowed=*/false));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Give the newest cache a manifest entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    cache->set_manifest_parser_version(0);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void IfModifiedSinceUpgradeParserVersion1Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a cache without a manifest entry.  The manifest entry will be
-    // added later.
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), -1);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    AppCacheCacheTestHelper::CacheEntries cache_entries;
-
-    // Add cache entry for manifest.
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = std::move(headers);
-    AppCacheCacheTestHelper::AddCacheEntry(
-        &cache_entries, group_->manifest_url(), AppCacheEntry::EXPLICIT,
-        /*expect_if_modified_since=*/"Sat, 29 Oct 1994 19:43:31 GMT",
-        /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-        std::move(response_info), kManifest1Contents);
-
-    // Add all header checks from |cache_entries|.
-    for (const auto& kvp : cache_entries) {
-      const GURL& cache_entry_url = kvp.first;
-      const AppCacheCacheTestHelper::CacheEntry* cache_entry = kvp.second.get();
-      http_headers_request_test_jobs_.emplace(
-          cache_entry_url,
-          std::make_unique<HttpHeadersRequestTestJob>(
-              cache_entry->expect_if_modified_since,
-              cache_entry->expect_if_none_match, cache_entry->headers_allowed));
-    }
-
-    cache_helper_ = std::make_unique<AppCacheCacheTestHelper>(
-        service_.get(), group_->manifest_url(), cache, std::move(cache_entries),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-    cache_helper_->Write();
-
-    // Start update after data write completes asynchronously.
-  }
-
-  // AppCaches built with manifest parser version 0 should update without
-  // conditional request headers to force the server to send a 200 response
-  // back to the client rather than 304.  This test ensures that, when the cache
-  // has a response info with cached ETag headers, the request does not include
-  // an If-None-Match conditioanl header.
-  void IfNoneMatchUpgradeParserVersion0Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), std::string(),
-                                    /*headers_allowed=*/false));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Give the newest cache a manifest entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    cache->set_manifest_parser_version(0);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected manifest response info that will cause
-    // an If-None-Match header to be put in the manifest fetch request.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "ETag: \"LadeDade\"\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void IfNoneMatchUpgradeParserVersion1Test() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), "\"LadeDade\""));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Give the newest cache a manifest entry that is in storage.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST1;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with expected manifest response info that will cause
-    // an If-None-Match header to be put in the manifest fetch request.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "ETag: \"LadeDade\"\0"
-        "\0";
-    scoped_refptr<net::HttpResponseHeaders> headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(
-            std::string(data, base::size(data)));
-    std::unique_ptr<net::HttpResponseInfo> response_info =
-        std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = std::move(headers);
-    scoped_refptr<HttpResponseInfoIOBuffer> io_buffer =
-        base::MakeRefCounted<HttpResponseInfoIOBuffer>(
-            std::move(response_info));
-    response_writer_->WriteInfo(
-        io_buffer.get(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void RequestResponseTimesAreSetTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), MockHttpServer::GetMockUrl("files/manifest1"),
-        111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a cache without a manifest entry.  The manifest entry will be
-    // added later.
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), -1);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = false;
-
-    AppCacheCacheTestHelper::CacheEntries cache_entries;
-
-    // Add cache entry for manifest.
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    {
-      const char data[] =
-          "HTTP/1.1 200 OK\0"
-          "Last-Modified: Sat, 29 Oct 2019 19:43:31 GMT\0";
-      scoped_refptr<net::HttpResponseHeaders> headers =
-          base::MakeRefCounted<net::HttpResponseHeaders>(
-              std::string(data, base::size(data)));
-      std::unique_ptr<net::HttpResponseInfo> response_info =
-          std::make_unique<net::HttpResponseInfo>();
-      response_info->headers = std::move(headers);
-      response_info->request_time = base::Time::Now() - kOneYear;
-      response_info->response_time = base::Time::Now() - kOneYear;
-      AppCacheCacheTestHelper::AddCacheEntry(
-          &cache_entries, group_->manifest_url(), AppCacheEntry::EXPLICIT,
-          /*expect_if_modified_since=*/std::string(),
-          /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-          std::move(response_info), kManifest1Contents);
-    }
-
-    cache_helper_ = std::make_unique<AppCacheCacheTestHelper>(
-        service_.get(), group_->manifest_url(), cache, std::move(cache_entries),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-    cache_helper_->Write();
-
-    post_update_finished_cb_ = base::BindOnce(
-        &AppCacheUpdateJobTest::RequestResponseTimesAreSetUpdateFinished,
-        base::Unretained(this));
-
-    // Start update after data write completes asynchronously.
-    // After update is finished, continues async in
-    // |RequestResponseTimesAreSetUpdateFinished|.
-  }
-
-  void RequestResponseTimesAreSetUpdateFinished() {
-    ASSERT_NE(group_->newest_complete_cache(), cache_helper_->write_cache());
-    ASSERT_NE(group_->newest_complete_cache(), nullptr);
-    cache_helper_->PrepareForRead(
-        group_->newest_complete_cache(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::RequestResponseTimesAreSetReadFinished,
-            base::Unretained(this)));
-    cache_helper_->Read();
-    // Continues async in |RequestResponseTimesAreSetReadFinished|.
-  }
-
-  void RequestResponseTimesAreSetReadFinished() {
-    auto it = cache_helper_->read_cache_entries().find(
-        MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_NE(it, cache_helper_->read_cache_entries().end());
-    CHECK_GT(it->second->response_info->request_time,
-             base::Time::Now() - kOneHour);
-    CHECK_GT(it->second->response_info->response_time,
-             base::Time::Now() - kOneHour);
-    TriggerTestComplete();
-    // Continues async in |TestComplete|.
-  }
-
-  void RequestResponseTimesAreModifiedTest() {
-    RequestResponseTimesModified(/*feature_enabled=*/true);
-  }
-
-  void RequestResponseTimesAreNotModifiedTest() {
-    RequestResponseTimesModified(/*feature_enabled=*/false);
-  }
-
-  void RequestResponseTimesModified(bool feature_enabled) {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest1-with-notmodified"), 111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a cache without a manifest entry.  The manifest entry will be
-    // added later.
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), -1);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST1_WITH_NOTMODIFIED;
-    if (feature_enabled) {
-      expect_old_cache_ = cache;
-    }
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    AppCacheCacheTestHelper::CacheEntries cache_entries;
-
-    // Add cache entry for manifest.
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    {
-      const char data[] =
-          "HTTP/1.1 200 OK\0"
-          "Last-Modified: Sat, 29 Oct 2019 19:43:31 GMT\0";
-      scoped_refptr<net::HttpResponseHeaders> headers =
-          base::MakeRefCounted<net::HttpResponseHeaders>(
-              std::string(data, base::size(data)));
-      std::unique_ptr<net::HttpResponseInfo> response_info =
-          std::make_unique<net::HttpResponseInfo>();
-      response_info->headers = std::move(headers);
-      response_info->request_time = base::Time::Now() - kOneYear;
-      response_info->response_time = base::Time::Now() - kOneYear;
-      AppCacheCacheTestHelper::AddCacheEntry(
-          &cache_entries, group_->manifest_url(), AppCacheEntry::EXPLICIT,
-          /*expect_if_modified_since=*/std::string(),
-          /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-          std::move(response_info), kManifest1WithNotModifiedContents);
-    }
-
-    // Add cache entry for notmodified.
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    {
-      const char data[] =
-          "HTTP/1.1 200 OK\0"
-          "Last-Modified: Sat, 29 Oct 2019 19:43:31 GMT\0";
-      scoped_refptr<net::HttpResponseHeaders> headers =
-          base::MakeRefCounted<net::HttpResponseHeaders>(
-              std::string(data, base::size(data)));
-      std::unique_ptr<net::HttpResponseInfo> response_info =
-          std::make_unique<net::HttpResponseInfo>();
-      response_info->headers = std::move(headers);
-      // Leave the request and response time fields unset to match corrupt
-      // cases in the field.
-      CHECK_EQ(response_info->request_time, base::Time());
-      CHECK_EQ(response_info->response_time, base::Time());
-      AppCacheCacheTestHelper::AddCacheEntry(
-          &cache_entries, MockHttpServer::GetMockUrl("files/notmodified"),
-          AppCacheEntry::EXPLICIT,
-          /*expect_if_modified_since=*/"Sat, 29 Oct 2019 19:43:31 GMT",
-          /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-          std::move(response_info), /*body=*/"laughing-giraffe");
-    }
-
-    // Add all header checks from |cache_entries|.
-    for (auto& it : cache_entries) {
-      http_headers_request_test_jobs_.emplace(
-          it.first,
-          std::make_unique<HttpHeadersRequestTestJob>(
-              it.second->expect_if_modified_since,
-              it.second->expect_if_none_match, it.second->headers_allowed));
-    }
-
-    cache_helper_ = std::make_unique<AppCacheCacheTestHelper>(
-        service_.get(), group_->manifest_url(), cache, std::move(cache_entries),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-    cache_helper_->Write();
-
-    post_update_finished_cb_ = base::BindOnce(
-        &AppCacheUpdateJobTest::RequestResponseTimesModifiedUpdateFinished,
-        base::Unretained(this), feature_enabled);
-
-    // Start update after data write completes asynchronously.
-    // After update is finished, continues async in
-    // |RequestResponseTimesModifiedUpdateFinished|.
-  }
-
-  void RequestResponseTimesModifiedUpdateFinished(bool feature_enabled) {
-    ASSERT_NE(group_->newest_complete_cache(), cache_helper_->write_cache());
-    ASSERT_NE(group_->newest_complete_cache(), nullptr);
-    cache_helper_->PrepareForRead(
-        group_->newest_complete_cache(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::RequestResponseTimesModifiedReadFinished,
-            base::Unretained(this), feature_enabled));
-    cache_helper_->Read();
-    // Continues async in |RequestResponseTimesModifiedReadFinished|.
-  }
-
-  void RequestResponseTimesModifiedReadFinished(bool feature_enabled) {
-    auto it = cache_helper_->read_cache_entries().find(
-        MockHttpServer::GetMockUrl("files/notmodified"));
-    ASSERT_NE(it, cache_helper_->read_cache_entries().end());
-    // Verify that the cache body on the entry matches the originally written
-    // cache body.
-    CHECK_EQ(it->second->body, "laughing-giraffe");
-    if (feature_enabled) {
-      CHECK_GT(it->second->response_info->request_time,
-               base::Time::Now() - kOneHour);
-      CHECK_GT(it->second->response_info->response_time,
-               base::Time::Now() - kOneHour);
-    } else {
-      CHECK_EQ(it->second->response_info->request_time, base::Time());
-      CHECK_EQ(it->second->response_info->response_time, base::Time());
-    }
-    TriggerTestComplete();
-    // Continues async in |TestComplete|.
-  }
-
-  void RequestResponseTimesCorruptionFixedTest() {
-    RequestResponseTimesCorruption(/*expect_modified=*/true);
-  }
-
-  void RequestResponseTimesCorruptionNotFixedTest() {
-    RequestResponseTimesCorruption(/*expect_modified=*/false);
-  }
-
-  void RequestResponseTimesCorruption(bool expect_modified) {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl("files/manifest1-with-maybemodified"), 111);
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create a cache without a manifest entry.  The manifest entry will be
-    // added later.
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(), -1);
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    host->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = MANIFEST1_WITH_MAYBEMODIFIED;
-    if (!expect_modified) {
-      expect_old_cache_ = cache;
-    }
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    AppCacheCacheTestHelper::CacheEntries cache_entries;
-
-    // Add cache entry for manifest.
-    // Seed storage with expected manifest response info that will cause
-    // an If-Modified-Since header to be put in the manifest fetch request.
-    {
-      const char data[] =
-          "HTTP/1.1 200 OK\0"
-          "Last-Modified: Sat, 29 Oct 2019 19:43:31 GMT\0";
-      scoped_refptr<net::HttpResponseHeaders> headers =
-          base::MakeRefCounted<net::HttpResponseHeaders>(
-              std::string(data, base::size(data)));
-      std::unique_ptr<net::HttpResponseInfo> response_info =
-          std::make_unique<net::HttpResponseInfo>();
-      response_info->headers = std::move(headers);
-      response_info->request_time = base::Time::Now() - kOneYear;
-      response_info->response_time = base::Time::Now() - kOneYear;
-      AppCacheCacheTestHelper::AddCacheEntry(
-          &cache_entries, group_->manifest_url(), AppCacheEntry::EXPLICIT,
-          /*expect_if_modified_since=*/std::string(),
-          /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-          std::move(response_info), kManifest1WithMaybeModifiedContents);
-    }
-
-    // Add cache entry for maybemodified.
-    // Seed storage with expected cache response info that will cause
-    // an If-Modified-Since header to be put in the fetch request.
-    {
-      const char data[] =
-          "HTTP/1.1 200 OK\0"
-          "Last-Modified: Sat, 29 Oct 2019 19:43:31 GMT\0";
-      scoped_refptr<net::HttpResponseHeaders> headers =
-          base::MakeRefCounted<net::HttpResponseHeaders>(
-              std::string(data, base::size(data)));
-      std::unique_ptr<net::HttpResponseInfo> response_info =
-          std::make_unique<net::HttpResponseInfo>();
-      response_info->headers = std::move(headers);
-      CHECK_EQ(response_info->request_time, base::Time());
-      CHECK_EQ(response_info->response_time, base::Time());
-      std::string expect_if_modified_since;
-      if (!expect_modified) {
-        expect_if_modified_since = "Sat, 29 Oct 2019 19:43:31 GMT";
-      }
-      AppCacheCacheTestHelper::AddCacheEntry(
-          &cache_entries, MockHttpServer::GetMockUrl("files/maybemodified"),
-          AppCacheEntry::EXPLICIT,
-          /*expect_if_modified_since=*/expect_if_modified_since,
-          /*expect_if_none_match=*/std::string(), /*headers_allowed=*/true,
-          std::move(response_info), /*body=*/"cached-maybemodified");
-    }
-
-    // Add all header checks from |cache_entries|.
-    for (auto& it : cache_entries) {
-      http_headers_request_test_jobs_.emplace(
-          it.first,
-          std::make_unique<HttpHeadersRequestTestJob>(
-              it.second->expect_if_modified_since,
-              it.second->expect_if_none_match, it.second->headers_allowed));
-    }
-
-    cache_helper_ = std::make_unique<AppCacheCacheTestHelper>(
-        service_.get(), group_->manifest_url(), cache, std::move(cache_entries),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-    cache_helper_->Write();
-
-    post_update_finished_cb_ = base::BindOnce(
-        &AppCacheUpdateJobTest::RequestResponseTimesCorruptionUpdateFinished,
-        base::Unretained(this), expect_modified);
-
-    // Start update after data write completes asynchronously.
-    // After update is finished, continues async in
-    // |RequestResponseTimesCorruptionUpdateFinished|.
-  }
-
-  void RequestResponseTimesCorruptionUpdateFinished(bool expect_modified) {
-    // After cache write was complete, we note that we expect an item to be
-    // copied for the not modified case.
-    if (!expect_modified) {
-      expect_response_ids_.insert(std::map<GURL, int64_t>::value_type(
-          MockHttpServer::GetMockUrl("files/maybemodified"),
-          expect_old_cache_
-              ->GetEntry(MockHttpServer::GetMockUrl("files/maybemodified"))
-              ->response_id()));  // copied
-    }
-    ASSERT_NE(group_->newest_complete_cache(), cache_helper_->write_cache());
-    ASSERT_NE(group_->newest_complete_cache(), nullptr);
-    cache_helper_->PrepareForRead(
-        group_->newest_complete_cache(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::RequestResponseTimesCorruptionReadFinished,
-            base::Unretained(this), expect_modified));
-    cache_helper_->Read();
-    // Continues async in |RequestResponseTimesCorruptionReadFinished|.
-  }
-
-  void RequestResponseTimesCorruptionReadFinished(bool expect_modified) {
-    std::string resource_name;
-    resource_name = "files/maybemodified";
-    auto it = cache_helper_->read_cache_entries().find(
-        MockHttpServer::GetMockUrl(resource_name));
-    ASSERT_NE(it, cache_helper_->read_cache_entries().end());
-    if (expect_modified) {
-      // Verify that the cache body on the entry matches the expected mock
-      // return body.
-      CHECK_EQ(it->second->body, "modified");
-      CHECK_GT(it->second->response_info->request_time,
-               base::Time::Now() - kOneHour);
-      CHECK_GT(it->second->response_info->response_time,
-               base::Time::Now() - kOneHour);
-    } else {
-      CHECK_EQ(it->second->body, "cached-maybemodified");
-      CHECK_EQ(it->second->response_info->request_time, base::Time());
-      CHECK_EQ(it->second->response_info->response_time, base::Time());
-    }
-    TriggerTestComplete();
-    // Continues async in |TestComplete|.
-  }
-
-  void IfNoneMatchRefetchTest() {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://headertest"), 111);
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(), std::make_unique<HttpHeadersRequestTestJob>(
-                                    std::string(), "\"LadeDade\""));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Simulate a refetch manifest request that uses an ETag header.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "ETag: \"LadeDade\"\0"
-        "\0";
-    auto response_info = std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(data, base::size(data)));
-
-    group_->update_status_ = AppCacheGroup::DOWNLOADING;
-    update->manifest_response_info_ = std::move(response_info);
-    update->internal_state_ = AppCacheUpdateJobState::REFETCH_MANIFEST;
-    update->RefetchManifest();
-
-    // We need to wait for the URL load requests to make it to the
-    // URLLoaderInterceptor.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                       base::Unretained(this), update));
-
-    TriggerTestComplete();
-  }
-
-  void MultipleHeadersRefetchTest() {
-    // Verify that code is correct when building multiple extra headers.
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL("http://headertest"), 111);
-    http_headers_request_test_jobs_.emplace(
-        group_->manifest_url(),
-        std::make_unique<HttpHeadersRequestTestJob>(
-            "Sat, 29 Oct 1994 19:43:31 GMT", "\"LadeDade\""));
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Simulate a refetch manifest request that uses an ETag header.
-    const char data[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "ETag: \"LadeDade\"\0"
-        "\0";
-    auto response_info = std::make_unique<net::HttpResponseInfo>();
-    response_info->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
-        std::string(data, base::size(data)));
-
-    group_->update_status_ = AppCacheGroup::DOWNLOADING;
-    update->manifest_response_info_ = std::move(response_info);
-    update->internal_state_ = AppCacheUpdateJobState::REFETCH_MANIFEST;
-    update->RefetchManifest();
-
-    // We need to wait for the URL load requests to make it to the
-    // URLLoaderInterceptor.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&AppCacheUpdateJobTest::VerifyHeadersAndDeleteUpdate,
-                       base::Unretained(this), update));
-
-    TriggerTestComplete();
-  }
-
-  void CrossOriginHttpsSuccessTest() {
-    GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
-        "files/valid_cross_origin_https_manifest");
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    tested_manifest_ = NONE;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void CrossOriginHttpsDeniedTest() {
-    GURL manifest_url = MockHttpServer::GetMockHttpsUrl(
-        "files/invalid_cross_origin_https_manifest");
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    tested_manifest_ = NONE;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void OriginTrialUpdateTest() {
-    expect_token_expires_ = kTestOriginTrialTokenExpiry;
-    MakeService();
-    tested_manifest_path_override_ = "files/manifest2-origin-trial";
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(),
-        MockHttpServer::GetMockUrl(tested_manifest_path_override_),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        response_writer_->response_id());
-    MockFrontend* frontend1 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    host1->AssociateCompleteCache(cache);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = MANIFEST2_WITH_FILES_SCOPE;
-
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);  // final
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with identical manifest2 contents
-    const std::string seed_data(kManifest2Contents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void OriginTrialRequiredNoTokenTest() {
-    GURL manifest_url = MockHttpServer::GetMockUrl("files/manifest1");
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    ASSERT_TRUE(group_->last_full_update_check_time().is_null());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = false;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  void WaitForUpdateToFinish() {
-    if (group_->update_status() == AppCacheGroup::IDLE)
-      UpdateFinished();
-    else
-      group_->AddUpdateObserver(this);
-  }
-
-  void OnUpdateComplete(AppCacheGroup* group) override {
-    ASSERT_EQ(group_.get(), group);
-    protect_newest_cache_ = group->newest_complete_cache();
-    UpdateFinished();
-  }
-
-  void UpdateFinished() {
-    if (post_update_finished_cb_) {
-      std::move(post_update_finished_cb_).Run();
-      return;
-    }
-
-    TriggerTestComplete();
-  }
-
-  void TriggerTestComplete() {
-    // We unwind the stack prior to finishing up to let stack-based objects
-    // get deleted.
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
-        FROM_HERE, base::BindOnce(&AppCacheUpdateJobTest::TestComplete,
-                                  base::Unretained(this)));
-  }
-
-  void TestComplete() {
-    EXPECT_EQ(AppCacheGroup::IDLE, group_->update_status());
-    EXPECT_TRUE(group_->update_job() == nullptr);
-    if (do_checks_after_update_finished_)
-      VerifyExpectations();
-
-    // Clean up everything that was created on the IO thread.
-    cache_helper_.reset();
-    protect_newest_cache_ = nullptr;
-    group_ = nullptr;
-    hosts_.clear();
-    frontends_.clear();
-    response_infos_.clear();
-    service_.reset(nullptr);
-
-    std::move(test_completed_cb_).Run();
-  }
-
-  void MakeService() {
-    service_ = std::make_unique<MockAppCacheService>(
-        weak_partition_factory_->GetWeakPtr());
-  }
-
-  AppCache* MakeCacheForGroup(int64_t cache_id, int64_t manifest_response_id) {
-    return MakeCacheForGroup(cache_id, group_->manifest_url(),
-                             manifest_response_id);
-  }
-
-  AppCache* MakeCacheForGroup(int64_t cache_id,
-                              const GURL& manifest_entry_url,
-                              int64_t manifest_response_id) {
-    AppCache* cache = new AppCache(service_->storage(), cache_id);
-    cache->set_complete(true);
-    cache->set_manifest_parser_version(2);
-    cache->set_manifest_scope("/");
-    cache->set_update_time(base::Time::Now() - kOneHour);
-    group_->AddCache(cache);
-    group_->set_last_full_update_check_time(cache->update_time());
-
-    // Add manifest entry to cache.
-    if (manifest_response_id >= 0) {
-      cache->AddEntry(manifest_entry_url, AppCacheEntry(AppCacheEntry::MANIFEST,
-                                                        manifest_response_id));
-    }
-
-    // Specific tests that expect a newer time should set
-    // expect_full_update_time_newer_than_ which causes this
-    // equality expectation to be ignored.
-    expect_full_update_time_equal_to_ = cache->update_time();
-
-    return cache;
-  }
-
-  AppCacheHost* MakeHost(blink::mojom::AppCacheFrontend* frontend) {
-    constexpr int kRenderFrameIdForTests = 456;
-    hosts_.push_back(std::make_unique<AppCacheHost>(
-        base::UnguessableToken::Create(), process_id_, kRenderFrameIdForTests,
-        ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-            process_id_),
-        mojo::NullRemote(), service_.get()));
-    hosts_.back()->set_frontend_for_testing(frontend);
-    return hosts_.back().get();
-  }
-
-  AppCacheResponseInfo* MakeAppCacheResponseInfo(
-      const GURL& manifest_url,
-      int64_t response_id,
-      const std::string& raw_headers) {
-    std::unique_ptr<net::HttpResponseInfo> http_info =
-        std::make_unique<net::HttpResponseInfo>();
-    http_info->headers =
-        base::MakeRefCounted<net::HttpResponseHeaders>(raw_headers);
-    auto info = base::MakeRefCounted<AppCacheResponseInfo>(
-        service_->storage()->GetWeakPtr(), manifest_url, response_id,
-        std::move(http_info), 0);
-    response_infos_.emplace_back(info);
-    return info.get();
-  }
-
-  MockFrontend* MakeMockFrontend() {
-    frontends_.push_back(std::make_unique<MockFrontend>());
-    return frontends_.back().get();
-  }
-
-  // Verifies conditions about the group and notifications after an update
-  // has finished. Cannot verify update job internals as update is deleted.
-  void VerifyExpectations() {
-    RetryRequestTestJob::Verify();
-    for (auto& kvp : http_headers_request_test_jobs_) {
-      const GURL& test_job_url = kvp.first;
-      HttpHeadersRequestTestJob* test_job = kvp.second.get();
-      test_job->Verify(test_job_url);
-    }
-
-    EXPECT_EQ(expect_group_obsolete_, group_->is_obsolete());
-    EXPECT_EQ(expect_group_is_being_deleted_ || expect_eviction_,
-              group_->is_being_deleted());
-
-    if (!expect_eviction_) {
-      EXPECT_EQ(expect_evictable_error_,
-                !group_->first_evictable_error_time().is_null());
-      if (expect_evictable_error_) {
-        MockAppCacheStorage* storage =
-            static_cast<MockAppCacheStorage*>(service_->storage());
-        EXPECT_EQ(group_->first_evictable_error_time(),
-                  storage->stored_eviction_times_[group_->group_id()].second);
-      }
-    }
-
-    if (!expect_full_update_time_newer_than_.is_null()) {
-      EXPECT_LT(expect_full_update_time_newer_than_,
-                group_->last_full_update_check_time());
-    } else if (!expect_full_update_time_equal_to_.is_null()) {
-      EXPECT_EQ(expect_full_update_time_equal_to_,
-                group_->last_full_update_check_time());
-    }
-
-    if (expect_group_has_cache_) {
-      ASSERT_TRUE(group_->newest_complete_cache() != nullptr);
-      EXPECT_EQ(group_->newest_complete_cache()->manifest_parser_version(), 2);
-
-      if (expect_non_null_update_time_)
-        EXPECT_TRUE(!group_->newest_complete_cache()->update_time().is_null());
-
-      if (expect_old_cache_) {
-        EXPECT_NE(expect_old_cache_, group_->newest_complete_cache());
-        EXPECT_TRUE(base::Contains(group_->old_caches(), expect_old_cache_));
-      }
-      if (expect_newest_cache_) {
-        EXPECT_EQ(expect_newest_cache_, group_->newest_complete_cache());
-        EXPECT_FALSE(
-            base::Contains(group_->old_caches(), expect_newest_cache_));
-      } else {
-        // Tests that don't know which newest cache to expect contain updates
-        // that succeed (because the update creates a new cache whose pointer
-        // is unknown to the test). Check group and newest cache were stored
-        // when update succeeds.
-        MockAppCacheStorage* storage =
-            static_cast<MockAppCacheStorage*>(service_->storage());
-        EXPECT_TRUE(storage->IsGroupStored(group_.get()));
-        EXPECT_TRUE(storage->IsCacheStored(group_->newest_complete_cache()));
-
-        // Check that all entries in the newest cache were stored.
-        for (const auto& pair : group_->newest_complete_cache()->entries()) {
-          EXPECT_NE(blink::mojom::kAppCacheNoResponseId,
-                    pair.second.response_id());
-
-          // Check that any copied entries have the expected response id
-          // and that entries that are not copied have a different response id.
-          auto found = expect_response_ids_.find(pair.first);
-          if (found != expect_response_ids_.end()) {
-            EXPECT_EQ(found->second, pair.second.response_id());
-          } else if (expect_old_cache_) {
-            AppCacheEntry* old_entry = expect_old_cache_->GetEntry(pair.first);
-            if (old_entry)
-              EXPECT_NE(old_entry->response_id(), pair.second.response_id());
-          }
-        }
-      }
-    } else {
-      EXPECT_TRUE(group_->newest_complete_cache() == nullptr);
-    }
-
-    // Verify token_expires times on cache.
-    if (expect_group_has_cache_) {
-      AppCache* cache = group_->newest_complete_cache();
-      ASSERT_TRUE(cache);
-      EXPECT_EQ(cache->token_expires(), expect_token_expires_);
-    }
-
-    // Check expected events.
-    for (const std::unique_ptr<MockFrontend>& frontend : frontends_) {
-      MockFrontend::RaisedEvents& expected_events = frontend->expected_events_;
-      MockFrontend::RaisedEvents& actual_events = frontend->raised_events_;
-      ASSERT_EQ(expected_events.size(), actual_events.size());
-
-      // Check each expected event.
-      for (size_t j = 0; j < expected_events.size() && j < actual_events.size();
-           ++j) {
-        EXPECT_EQ(expected_events[j], actual_events[j]);
-      }
-
-      if (!frontend->expected_error_message_.empty()) {
-        EXPECT_EQ(frontend->expected_error_message_, frontend->error_message_);
-      }
-    }
-
-    // Verify expected cache contents last as some checks are asserts
-    // and will abort the test if they fail.
-    if (tested_manifest_) {
-      AppCache* cache = group_->newest_complete_cache();
-      ASSERT_TRUE(cache != nullptr);
-      EXPECT_EQ(group_.get(), cache->owning_group());
-      EXPECT_TRUE(cache->is_complete());
-
-      switch (tested_manifest_) {
-        case MANIFEST1:
-          VerifyManifest1(cache);
-          break;
-        case MANIFEST1_WITH_NOTMODIFIED:
-          VerifyManifest1WithNotModified(cache);
-          break;
-        case MANIFEST1_WITH_MAYBEMODIFIED:
-          VerifyManifest1WithMaybeModified(cache);
-          break;
-        case MANIFEST2_WITH_ROOT_SCOPE:
-          VerifyManifest2WithRootScope(cache);
-          break;
-        case MANIFEST2_WITH_FILES_SCOPE:
-          VerifyManifest2WithFilesScope(cache);
-          break;
-        case MANIFEST_MERGED_TYPES:
-          VerifyManifestMergedTypes(cache);
-          break;
-        case EMPTY_MANIFEST:
-          VerifyEmptyManifest(cache);
-          break;
-        case EMPTY_FILE_MANIFEST:
-          VerifyEmptyFileManifest(cache);
-          break;
-        case PENDING_MASTER_NO_UPDATE:
-          VerifyMasterEntryNoUpdate(cache);
-          break;
-        case MANIFEST_WITH_INTERCEPT:
-          VerifyManifestWithIntercept(cache);
-          break;
-        case SCOPE_MANIFEST_ROOT:
-          VerifyScopeManifest(cache);
-          break;
-        case SCOPE_MANIFEST_BAR:
-          VerifyScopeManifest(cache);
-          break;
-        case SCOPE_MANIFEST_OTHER:
-          VerifyScopeManifest(cache);
-          break;
-        case NONE:
-        default:
-          break;
-      }
-    }
-  }
-
-  void VerifyManifest1(AppCache* cache) {
-    size_t expected = 3 + expect_extra_entries_.size();
-    EXPECT_EQ(expected, cache->entries().size());
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/manifest1";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types());
-
-    for (const auto& pair : expect_extra_entries_) {
-      entry = cache->GetEntry(pair.first);
-      ASSERT_TRUE(entry);
-      EXPECT_EQ(pair.second.types(), entry->types());
-    }
-
-    expected = 1;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/fallback1a")));
-
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifest1WithNotModified(AppCache* cache) {
-    size_t expected = 4 + expect_extra_entries_.size();
-    EXPECT_EQ(expected, cache->entries().size());
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/manifest1-with-notmodified";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/notmodified"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types());
-
-    for (const auto& pair : expect_extra_entries_) {
-      entry = cache->GetEntry(pair.first);
-      ASSERT_TRUE(entry);
-      EXPECT_EQ(pair.second.types(), entry->types());
-    }
-
-    expected = 1;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/fallback1a")));
-
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifest1WithMaybeModified(AppCache* cache) {
-    size_t expected = 4 + expect_extra_entries_.size();
-    EXPECT_EQ(expected, cache->entries().size());
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/manifest1-with-maybemodified";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/maybemodified"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::FALLBACK, entry->types());
-
-    for (const auto& pair : expect_extra_entries_) {
-      entry = cache->GetEntry(pair.first);
-      ASSERT_TRUE(entry);
-      EXPECT_EQ(pair.second.types(), entry->types());
-    }
-
-    expected = 1;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/fallback1a")));
-
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifest2WithRootScope(AppCache* cache) {
-    size_t expected = 6 + expect_extra_entries_.size();
-    EXPECT_EQ(expected, cache->entries().size());
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/manifest2-with-root-override";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsManifest());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsFallback());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback2a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsFallback());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsIntercept());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept2a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsIntercept());
-
-    for (const auto& pair : expect_extra_entries_) {
-      entry = cache->GetEntry(pair.first);
-      ASSERT_TRUE(entry);
-      EXPECT_EQ(pair.second.types(), entry->types());
-    }
-
-    expected = 2;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/fallback1a")));
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[1] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("bar/fallback2"),
-                          MockHttpServer::GetMockUrl("files/fallback2a")));
-
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifest2WithFilesScope(AppCache* cache) {
-    size_t expected = 4 + expect_extra_entries_.size();
-    EXPECT_EQ(expected, cache->entries().size());
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/manifest2";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-    EXPECT_TRUE(entry->IsManifest());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsExplicit());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsIntercept());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/fallback1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsFallback());
-
-    for (const auto& pair : expect_extra_entries_) {
-      entry = cache->GetEntry(pair.first);
-      ASSERT_TRUE(entry);
-      EXPECT_EQ(pair.second.types(), entry->types());
-    }
-
-    expected = 1;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/fallback1a")));
-
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifestMergedTypes(AppCache* cache) {
-    size_t expected = 2;
-    EXPECT_EQ(expected, cache->entries().size());
-    AppCacheEntry* entry = cache->GetEntry(
-        MockHttpServer::GetMockUrl("files/manifest-merged-types"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MANIFEST,
-              entry->types());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::FALLBACK |
-                  AppCacheEntry::MASTER,
-              entry->types());
-
-    expected = 1;
-    ASSERT_EQ(expected, cache->fallback_namespaces_.size());
-    EXPECT_TRUE(
-        cache->fallback_namespaces_[0] ==
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("files/fallback1"),
-                          MockHttpServer::GetMockUrl("files/explicit1")));
-
-    EXPECT_EQ(expected, cache->online_safelist_namespaces_.size());
-    EXPECT_TRUE(cache->online_safelist_namespaces_[0] ==
-                AppCacheNamespace(APPCACHE_NETWORK_NAMESPACE,
-                                  MockHttpServer::GetMockUrl("files/online1"),
-                                  GURL()));
-    EXPECT_FALSE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyEmptyManifest(AppCache* cache) {
-    const char* kManifestPath = tested_manifest_path_override_
-                                    ? tested_manifest_path_override_
-                                    : "files/empty-manifest";
-    size_t expected = 1;
-    EXPECT_EQ(expected, cache->entries().size());
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-
-    EXPECT_TRUE(cache->fallback_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_FALSE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyEmptyFileManifest(AppCache* cache) {
-    EXPECT_EQ(size_t(2), cache->entries().size());
-    AppCacheEntry* entry = cache->GetEntry(
-        MockHttpServer::GetMockUrl("files/empty-file-manifest"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/empty1"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::EXPLICIT, entry->types());
-    EXPECT_TRUE(entry->has_response_id());
-
-    EXPECT_TRUE(cache->fallback_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_FALSE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyMasterEntryNoUpdate(AppCache* cache) {
-    EXPECT_EQ(size_t(3), cache->entries().size());
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl("files/notmodified"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit1"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MASTER, entry->types());
-    EXPECT_TRUE(entry->has_response_id());
-
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/explicit2"));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::EXPLICIT | AppCacheEntry::MASTER, entry->types());
-    EXPECT_TRUE(entry->has_response_id());
-
-    EXPECT_TRUE(cache->fallback_namespaces_.empty());
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_FALSE(cache->online_safelist_all_);
-
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-  }
-
-  void VerifyManifestWithIntercept(AppCache* cache) {
-    EXPECT_EQ(2u, cache->entries().size());
-    const char* kManifestPath = "files/manifest-with-intercept";
-    AppCacheEntry* entry =
-        cache->GetEntry(MockHttpServer::GetMockUrl(kManifestPath));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-    entry = cache->GetEntry(MockHttpServer::GetMockUrl("files/intercept1a"));
-    ASSERT_TRUE(entry);
-    EXPECT_TRUE(entry->IsIntercept());
-  }
-
-  bool CheckNamespaceExists(const std::vector<AppCacheNamespace>& namespaces,
-                            const AppCacheNamespace& namespace_entry) {
-    for (const AppCacheNamespace& appcache_namespace : namespaces) {
-      if (appcache_namespace == namespace_entry)
-        return true;
-    }
-    return false;
-  }
-
-  std::vector<AppCacheNamespace> GetExpectedScopeIntercepts() {
-    std::vector<AppCacheNamespace> expected;
-
-    // Set up the expected intercepts.
-    std::vector<AppCacheNamespace> expected_root = {
-        AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
-                          MockHttpServer::GetMockUrl(""),
-                          MockHttpServer::GetMockUrl("intercept-newroot/foo")),
-    };
-    std::vector<AppCacheNamespace> expected_bar = {
-        AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
-                          MockHttpServer::GetMockUrl("bar/foo"),
-                          MockHttpServer::GetMockUrl("intercept-newbar/foo")),
-        AppCacheNamespace(
-            APPCACHE_INTERCEPT_NAMESPACE,
-            MockHttpServer::GetMockUrl("bar/baz/foo"),
-            MockHttpServer::GetMockUrl("intercept-newbar/newbaz/foo")),
-    };
-    std::vector<AppCacheNamespace> expected_other = {
-        AppCacheNamespace(APPCACHE_INTERCEPT_NAMESPACE,
-                          MockHttpServer::GetMockUrl("other/foo"),
-                          MockHttpServer::GetMockUrl("intercept-newother/foo")),
-    };
-
-    switch (tested_manifest_) {
-      case SCOPE_MANIFEST_ROOT:
-        expected.insert(expected.end(), std::begin(expected_root),
-                        std::end(expected_root));
-        expected.insert(expected.end(), std::begin(expected_bar),
-                        std::end(expected_bar));
-        expected.insert(expected.end(), std::begin(expected_other),
-                        std::end(expected_other));
-        break;
-      case SCOPE_MANIFEST_BAR:
-        expected.insert(expected.end(), std::begin(expected_bar),
-                        std::end(expected_bar));
-        break;
-      case SCOPE_MANIFEST_OTHER:
-        expected.insert(expected.end(), std::begin(expected_other),
-                        std::end(expected_other));
-        break;
-      default:
-        NOTREACHED();
-    }
-
-    return expected;
-  }
-
-  std::vector<AppCacheNamespace> GetExpectedScopeFallbacks() {
-    std::vector<AppCacheNamespace> expected;
-
-    // Set up the expected fallbacks.
-    std::vector<AppCacheNamespace> expected_root = {
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl(""),
-                          MockHttpServer::GetMockUrl("fallback-newroot/foo")),
-    };
-    std::vector<AppCacheNamespace> expected_bar = {
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("bar/foo"),
-                          MockHttpServer::GetMockUrl("fallback-newbar/foo")),
-        AppCacheNamespace(
-            APPCACHE_FALLBACK_NAMESPACE,
-            MockHttpServer::GetMockUrl("bar/baz/foo"),
-            MockHttpServer::GetMockUrl("fallback-newbar/newbaz/foo")),
-    };
-    std::vector<AppCacheNamespace> expected_other = {
-        AppCacheNamespace(APPCACHE_FALLBACK_NAMESPACE,
-                          MockHttpServer::GetMockUrl("other/foo"),
-                          MockHttpServer::GetMockUrl("fallback-newother/foo")),
-    };
-
-    switch (tested_manifest_) {
-      case SCOPE_MANIFEST_ROOT:
-        expected.insert(expected.end(), std::begin(expected_root),
-                        std::end(expected_root));
-        expected.insert(expected.end(), std::begin(expected_bar),
-                        std::end(expected_bar));
-        expected.insert(expected.end(), std::begin(expected_other),
-                        std::end(expected_other));
-        break;
-      case SCOPE_MANIFEST_BAR:
-        expected.insert(expected.end(), std::begin(expected_bar),
-                        std::end(expected_bar));
-        break;
-      case SCOPE_MANIFEST_OTHER:
-        expected.insert(expected.end(), std::begin(expected_other),
-                        std::end(expected_other));
-        break;
-      default:
-        NOTREACHED();
-    }
-
-    return expected;
-  }
-
-  void VerifyScopeManifest(AppCache* cache) {
-    std::vector<AppCacheNamespace> expected_intercepts =
-        GetExpectedScopeIntercepts();
-    std::vector<AppCacheNamespace> expected_fallbacks =
-        GetExpectedScopeFallbacks();
-
-    // Verify the number of cache entries.  There should be cache entries for
-    // the manifest, all of the expected intercepts (because each defines a
-    // separate target), and all of the expected fallbacks (because each also
-    // defines a separate target).
-    size_t expected_size =
-        1 + expected_intercepts.size() + expected_fallbacks.size();
-    EXPECT_EQ(expected_size, cache->entries().size());
-
-    // Verify basic cache details.
-    EXPECT_TRUE(cache->online_safelist_namespaces_.empty());
-    EXPECT_FALSE(cache->online_safelist_all_);
-    EXPECT_TRUE(cache->update_time_ > base::Time());
-
-    // Verify manifest.
-    ASSERT_TRUE(!std::string(tested_manifest_path_override_).empty());
-    AppCacheEntry* entry = cache->GetEntry(
-        MockHttpServer::GetMockUrl(tested_manifest_path_override_));
-    ASSERT_TRUE(entry);
-    EXPECT_EQ(AppCacheEntry::MANIFEST, entry->types());
-
-    // Verify intercepts.
-    ASSERT_EQ(expected_intercepts.size(), cache->intercept_namespaces_.size());
-    for (auto it = expected_intercepts.begin(); it != expected_intercepts.end();
-         ++it) {
-      EXPECT_EQ(it->type, APPCACHE_INTERCEPT_NAMESPACE);
-      entry = cache->GetEntry(it->target_url);
-      ASSERT_TRUE(entry);
-      EXPECT_TRUE(entry->IsIntercept());
-      EXPECT_TRUE(CheckNamespaceExists(cache->intercept_namespaces_, *it));
-    }
-
-    // Verify fallbacks.
-    for (auto it = expected_fallbacks.begin(); it != expected_fallbacks.end();
-         ++it) {
-      EXPECT_EQ(it->type, APPCACHE_FALLBACK_NAMESPACE);
-      entry = cache->GetEntry(it->target_url);
-      ASSERT_TRUE(entry);
-      EXPECT_TRUE(entry->IsFallback());
-      EXPECT_TRUE(CheckNamespaceExists(cache->fallback_namespaces_, *it));
-    }
-  }
-
- private:
-  // Various manifest files used in this test.
-  enum TestedManifest {
-    NONE,
-    MANIFEST1,
-    MANIFEST1_WITH_MAYBEMODIFIED,
-    MANIFEST1_WITH_NOTMODIFIED,
-    MANIFEST2_WITH_ROOT_SCOPE,
-    MANIFEST2_WITH_FILES_SCOPE,
-    MANIFEST_MERGED_TYPES,
-    EMPTY_MANIFEST,
-    EMPTY_FILE_MANIFEST,
-    PENDING_MASTER_NO_UPDATE,
-    MANIFEST_WITH_INTERCEPT,
-    SCOPE_MANIFEST_ROOT,
-    SCOPE_MANIFEST_BAR,
-    SCOPE_MANIFEST_OTHER,
-  };
-
-  void ScopeTest(const char* tested_manifest_path,
-                 const TestedManifest& tested_manifest) {
-    GURL manifest_url = MockHttpServer::GetMockUrl(tested_manifest_path);
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    ASSERT_TRUE(group_->last_full_update_check_time().is_null());
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_full_update_time_newer_than_ = base::Time::Now() - kOneHour;
-    tested_manifest_ = tested_manifest;
-    tested_manifest_path_override_ = tested_manifest_path;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    // Other events are only sent to associated hosts.
-
-    WaitForUpdateToFinish();
-  }
-
-  void AddExpectedProgressEvents(MockFrontend* frontend,
-                                 const int& number_of_progress_events) {
-    for (auto i = 0; i < number_of_progress_events; ++i) {
-      frontend->AddExpectedEvent(
-          blink::mojom::AppCacheEventID::APPCACHE_PROGRESS_EVENT);
-    }
-  }
-
-  void Scope304Test(const char* tested_manifest_path,
-                    const std::string& previous_scope,
-                    const TestedManifest& tested_manifest) {
-    GURL manifest_url = MockHttpServer::GetMockUrl(tested_manifest_path);
-
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), manifest_url, service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    // Create response writer to get a response id.
-    response_writer_ =
-        service_->storage()->CreateResponseWriter(group_->manifest_url());
-
-    int64_t manifest_response_id = response_writer_->response_id();
-    AppCache* cache = MakeCacheForGroup(service_->storage()->NewCacheId(),
-                                        manifest_response_id);
-    cache->set_manifest_scope(previous_scope);
-    MockFrontend* frontend1 = MakeMockFrontend();
-    MockFrontend* frontend2 = MakeMockFrontend();
-    AppCacheHost* host1 = MakeHost(frontend1);
-    AppCacheHost* host2 = MakeHost(frontend2);
-    host1->AssociateCompleteCache(cache);
-    host2->AssociateCompleteCache(cache);
-
-    // Seed the response_info working set with canned data so that an existing
-    // manifest is reused by the update job.
-    const char kData[] =
-        "HTTP/1.1 200 OK\0"
-        "Last-Modified: Sat, 29 Oct 1994 19:43:31 GMT\0"
-        "\0";
-    const std::string kRawHeaders(kData, base::size(kData));
-    MakeAppCacheResponseInfo(manifest_url, manifest_response_id, kRawHeaders);
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = true;
-    expect_old_cache_ = cache;
-    tested_manifest_ = tested_manifest;
-    tested_manifest_path_override_ = tested_manifest_path;
-
-    int number_of_progress_events = 0;
-    switch (tested_manifest_) {
-      case SCOPE_MANIFEST_ROOT:
-        number_of_progress_events = 9;
-        break;
-      case SCOPE_MANIFEST_BAR:
-        number_of_progress_events = 5;
-        break;
-      case SCOPE_MANIFEST_OTHER:
-        number_of_progress_events = 3;
-        break;
-      default:
-        NOTREACHED();
-    }
-
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    AddExpectedProgressEvents(frontend1, number_of_progress_events);
-    frontend1->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT);
-    AddExpectedProgressEvents(frontend2, number_of_progress_events);
-    frontend2->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_UPDATE_READY_EVENT);
-
-    // Seed storage with kScopeManifestContents so a possible scope change will
-    // result in reading this manifest data from the cache and re-parsing it
-    // with the new scope.
-    const std::string seed_data(kScopeManifestContents);
-    scoped_refptr<net::StringIOBuffer> io_buffer =
-        base::MakeRefCounted<net::StringIOBuffer>(seed_data);
-    response_writer_->WriteData(
-        io_buffer.get(), seed_data.length(),
-        base::BindOnce(
-            &AppCacheUpdateJobTest::StartUpdateAfterSeedingStorageData,
-            base::Unretained(this)));
-
-    // Start update after data write completes asynchronously.
-  }
-
-  void RetryRequestTest(bool expect_group_has_cache) {
-    MakeService();
-    group_ = base::MakeRefCounted<AppCacheGroup>(
-        service_->storage(), GURL(RetryRequestTestJob::kRetryUrl),
-        service_->storage()->NewGroupId());
-    AppCacheUpdateJob* update =
-        new AppCacheUpdateJob(service_.get(), group_.get());
-    group_->update_job_ = update;
-
-    MockFrontend* frontend = MakeMockFrontend();
-    AppCacheHost* host = MakeHost(frontend);
-    update->StartUpdate(host, GURL());
-
-    // Set up checks for when update job finishes.
-    do_checks_after_update_finished_ = true;
-    expect_group_obsolete_ = false;
-    expect_group_has_cache_ = expect_group_has_cache;
-    frontend->AddExpectedEvent(
-        blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT);
-
-    WaitForUpdateToFinish();
-  }
-
-  content::BrowserTaskEnvironment task_environment_;
-
-  std::unique_ptr<MockAppCacheService> service_;
-  scoped_refptr<AppCacheGroup> group_;
-  scoped_refptr<AppCache> protect_newest_cache_;
-  base::OnceClosure test_completed_cb_;
-  base::OnceClosure post_update_finished_cb_;
-
-  std::unique_ptr<AppCacheResponseWriter> response_writer_;
-  std::unique_ptr<AppCacheCacheTestHelper> cache_helper_;
-
-  // Hosts used by an async test that need to live until update job finishes.
-  // Otherwise, test can put host on the stack instead of here.
-  std::vector<std::unique_ptr<AppCacheHost>> hosts_;
-
-  // Response infos used by an async test that need to live until update job
-  // finishes.
-  std::vector<scoped_refptr<AppCacheResponseInfo>> response_infos_;
-
-  // Flag indicating if test cares to verify the update after update finishes.
-  bool do_checks_after_update_finished_;
-  bool expect_group_obsolete_;
-  bool expect_group_has_cache_;
-  bool expect_group_is_being_deleted_;
-  bool expect_evictable_error_;
-  bool expect_eviction_;
-  base::Time expect_full_update_time_newer_than_;
-  base::Time expect_full_update_time_equal_to_;
-  base::Time expect_token_expires_;
-  AppCache* expect_old_cache_;
-  AppCache* expect_newest_cache_;
-  bool expect_non_null_update_time_;
-  std::vector<std::unique_ptr<MockFrontend>>
-      frontends_;  // to check expected events
-  TestedManifest tested_manifest_;
-  const char* tested_manifest_path_override_;
-  AppCache::EntryMap expect_extra_entries_;
-  std::map<GURL, int64_t> expect_response_ids_;
-
-  URLLoaderInterceptor interceptor_;
-  const int process_id_;
-  std::map<GURL, std::unique_ptr<HttpHeadersRequestTestJob>>
-      http_headers_request_test_jobs_;
-
-  base::test::ScopedFeatureList appcache_require_origin_trial_feature_;
-  base::test::ScopedFeatureList appcache_disable_corruption_feature_;
-  blink::ScopedTestOriginTrialPolicy origin_trial_policy_;
-
-  // Lazily create these to avoid data races in the FeatureList between
-  // service workers (reading) and appcache tests (writing).
-  std::unique_ptr<content::TestBrowserContext> browser_context_;
-  std::unique_ptr<base::WeakPtrFactory<StoragePartitionImpl>>
-      weak_partition_factory_;
-};
-
-class AppCacheUpdateJobOriginTrialTest : public AppCacheUpdateJobTest {
- public:
-  AppCacheUpdateJobOriginTrialTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        blink::features::kAppCacheRequireOriginTrial);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-class AppCacheUpdateJobNoUpdateOn304Test : public AppCacheUpdateJobTest {
- public:
-  AppCacheUpdateJobNoUpdateOn304Test() = default;
-};
-
-class AppCacheUpdateJobWithCorruptionRecoveryTest
-    : public AppCacheUpdateJobTest {
- public:
-  AppCacheUpdateJobWithCorruptionRecoveryTest() {
-    scoped_feature_list_.InitAndEnableFeature(
-        kAppCacheCorruptionRecoveryFeature);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-class AppCacheUpdateJobWithoutCorruptionRecoveryTest
-    : public AppCacheUpdateJobTest {
- public:
-  AppCacheUpdateJobWithoutCorruptionRecoveryTest() {
-    scoped_feature_list_.InitAndDisableFeature(
-        kAppCacheCorruptionRecoveryFeature);
-  }
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_F(AppCacheUpdateJobTest, AlreadyChecking) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(
-      service.storage(), GURL("http://manifesturl.com"),
-      service.storage()->NewGroupId());
-
-  AppCacheUpdateJob update(&service, group.get());
-
-  // Pretend group is in checking state.
-  group->update_job_ = &update;
-  group->update_status_ = AppCacheGroup::CHECKING;
-
-  update.StartUpdate(nullptr, GURL());
-  EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
-
-  MockFrontend mock_frontend;
-  const int kMockProcessId1 = 1;
-  AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
-                    kMockProcessId1, /*render_frame_id=*/1,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kMockProcessId1),
-                    mojo::NullRemote(), &service);
-  host.set_frontend_for_testing(&mock_frontend);
-  update.StartUpdate(&host, GURL());
-
-  MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
-  ASSERT_EQ(1u, events.size());
-  EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT, events[0]);
-  EXPECT_EQ(AppCacheGroup::CHECKING, group->update_status());
-}
-
-TEST_F(AppCacheUpdateJobTest, AlreadyDownloading) {
-  MockAppCacheService service;
-  auto group = base::MakeRefCounted<AppCacheGroup>(
-      service.storage(), GURL("http://manifesturl.com"),
-      service.storage()->NewGroupId());
-
-  AppCacheUpdateJob update(&service, group.get());
-
-  // Pretend group is in downloading state.
-  group->update_job_ = &update;
-  group->update_status_ = AppCacheGroup::DOWNLOADING;
-
-  update.StartUpdate(nullptr, GURL());
-  EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
-
-  MockFrontend mock_frontend;
-  const int kMockProcessId1 = 1;
-  AppCacheHost host(/*host_id=*/base::UnguessableToken::Create(),
-                    kMockProcessId1, /*render_frame_id=*/1,
-                    ChildProcessSecurityPolicyImpl::GetInstance()->CreateHandle(
-                        kMockProcessId1),
-                    mojo::NullRemote(), &service);
-  host.set_frontend_for_testing(&mock_frontend);
-  update.StartUpdate(&host, GURL());
-
-  MockFrontend::RaisedEvents events = mock_frontend.raised_events_;
-  ASSERT_EQ(2u, events.size());
-  EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_CHECKING_EVENT, events[0]);
-  EXPECT_EQ(blink::mojom::AppCacheEventID::APPCACHE_DOWNLOADING_EVENT,
-            events[1]);
-
-  EXPECT_EQ(AppCacheGroup::DOWNLOADING, group->update_status());
-}
-
-TEST_F(AppCacheUpdateJobTest, StartCacheAttempt) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::StartCacheAttemptTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, StartUpgradeAttempt) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::StartUpgradeAttemptTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, CacheAttemptFetchManifestFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::CacheAttemptFetchManifestFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeFetchManifestFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeFetchManifestFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ManifestRedirect) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ManifestRedirectTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ManifestMissingMimeTypeTest) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ManifestMissingMimeTypeTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, ManifestNotFound) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ManifestNotFoundTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, ManifestGoneFetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ManifestGoneFetchTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, ManifestGoneUpgrade) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ManifestGoneUpgradeTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, CacheAttemptNotModified) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::CacheAttemptNotModifiedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeNotModified) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeNotModifiedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeNotModifiedVersion1) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeNotModifiedVersion1Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataChangedScopeUnchanged) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeManifestDataChangedScopeUnchangedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataChangedScopeChanged) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeManifestDataChangedScopeChangedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchangedScopeUnchanged) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeManifestDataUnchangedScopeUnchangedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeManifestDataUnchangedScopeChanged) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeManifestDataUnchangedScopeChangedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, Bug95101Test) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::Bug95101Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, BasicCacheAttemptSuccess) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::BasicCacheAttemptSuccessTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestRootWithNoOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestRootWithNoOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestBarWithNoOverrideTest) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::ScopeManifestBarWithNoOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestRootWithRootOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestRootWithRootOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestBarWithRootOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestBarWithRootOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestRootWithBarOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestRootWithBarOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestBarWithBarOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestBarWithBarOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestRootWithOtherOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestRootWithOtherOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifestBarWithOtherOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifestBarWithOtherOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304RootWithNoOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304RootWithNoOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304BarWithNoOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304BarWithNoOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304RootWithRootOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304RootWithRootOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304BarWithRootOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304BarWithRootOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304RootWithBarOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304RootWithBarOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304BarWithBarOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304BarWithBarOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304RootWithOtherOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304RootWithOtherOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, ScopeManifest304BarWithOtherOverrideTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::ScopeManifest304BarWithOtherOverrideTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, DownloadInterceptEntriesTest) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::DownloadInterceptEntriesTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, BasicUpgradeSuccess) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::BasicUpgradeSuccessTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCache) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeNoLoadFromNewestCache) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeNoLoadFromNewestCacheTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheVaryHeader) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheVaryHeaderTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeLoadFromNewestCacheReuseVaryHeader) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::UpgradeLoadFromNewestCacheReuseVaryHeaderTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeSuccessMergedTypes) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeSuccessMergedTypesTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, CacheAttemptFailUrlFetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::CacheAttemptFailUrlFetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeFailUrlFetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeFailUrlFetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeFailMasterUrlFetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeFailMasterUrlFetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, EmptyManifest) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::EmptyManifestTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, EmptyFile) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::EmptyFileTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, RetryRetryAfter) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RetryRetryAfterTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, RetryNoRetryAfter) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RetryNoRetryAfterTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, RetryNonzeroRetryAfter) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RetryNonzeroRetryAfterTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, RetrySuccess) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RetrySuccessTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, RetryUrl) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RetryUrlTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, FailStoreNewestCache) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::FailStoreNewestCacheTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryFailStoreNewestCacheTest) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::MasterEntryFailStoreNewestCacheTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeFailStoreNewestCache) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeFailStoreNewestCacheTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, UpgradeFailMakeGroupObsolete) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeFailMakeGroupObsoleteTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryFetchManifestFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryFetchManifestFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryBadManifest) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryBadManifestTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryManifestNotFound) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryManifestNotFoundTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryFailUrlFetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryFailUrlFetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryAllFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryAllFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntryAllFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeMasterEntryAllFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntrySomeFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntrySomeFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, UpgradeMasterEntrySomeFail) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::UpgradeMasterEntrySomeFailTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MasterEntryNoUpdate) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MasterEntryNoUpdateTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidCacheAttempt) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::StartUpdateMidCacheAttemptTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidNoUpdate) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::StartUpdateMidNoUpdateTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, StartUpdateMidDownload) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::StartUpdateMidDownloadTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, QueueMasterEntry) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::QueueMasterEntryTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfModifiedSinceCache) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::IfModifiedSinceTestCache);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfModifiedRefetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::IfModifiedTestRefetch);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfModifiedLastModified) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::IfModifiedTestLastModified);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgradeParserVersion0) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::IfModifiedSinceUpgradeParserVersion0Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfModifiedSinceUpgradeParserVersion1) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::IfModifiedSinceUpgradeParserVersion1Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgradeParserVersion0) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::IfNoneMatchUpgradeParserVersion0Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfNoneMatchUpgradeParserVersion1) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::IfNoneMatchUpgradeParserVersion1Test);
-}
-
-TEST_F(AppCacheUpdateJobTest, RequestResponseTimesAreSet) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::RequestResponseTimesAreSetTest);
-}
-
-TEST_F(AppCacheUpdateJobNoUpdateOn304Test, RequestResponseTimesAreNotModified) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::RequestResponseTimesAreNotModifiedTest);
-}
-
-TEST_F(AppCacheUpdateJobWithCorruptionRecoveryTest,
-       RequestResponseTimesCorruptionFixed) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::RequestResponseTimesCorruptionFixedTest);
-}
-
-TEST_F(AppCacheUpdateJobWithoutCorruptionRecoveryTest,
-       RequestResponseTimesCorruptionNotFixed) {
-  RunTestOnUIThread(
-      &AppCacheUpdateJobTest::RequestResponseTimesCorruptionNotFixedTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, IfNoneMatchRefetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::IfNoneMatchRefetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, MultipleHeadersRefetch) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::MultipleHeadersRefetchTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsSuccess) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::CrossOriginHttpsSuccessTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, CrossOriginHttpsDenied) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::CrossOriginHttpsDeniedTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, OriginTrialUpdateWithFeature) {
-  // Updating a manifest with a valid token should work
-  // with or without the kAppCacheRequireOriginTrial feature.
-  RunTestOnUIThread(&AppCacheUpdateJobTest::OriginTrialUpdateTest);
-}
-
-TEST_F(AppCacheUpdateJobTest, OriginTrialUpdateWithoutFeature) {
-  // The default AppCacheUpdateJobTest disables the origin trial.
-  RunTestOnUIThread(&AppCacheUpdateJobTest::OriginTrialUpdateTest);
-}
-
-TEST_F(AppCacheUpdateJobOriginTrialTest, OriginTrialRequiredNoToken) {
-  RunTestOnUIThread(&AppCacheUpdateJobTest::OriginTrialRequiredNoTokenTest);
-}
-
-}  // namespace appcache_update_job_unittest
-}  // namespace content
diff --git a/content/browser/appcache/chrome_appcache_service_unittest.cc b/content/browser/appcache/chrome_appcache_service_unittest.cc
deleted file mode 100644
index 82bca20d..0000000
--- a/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright (c) 2012 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 <set>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task/post_task.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache_database.h"
-#include "content/browser/appcache/appcache_storage_impl.h"
-#include "content/browser/appcache/appcache_test_helper.h"
-#include "content/browser/appcache/chrome_appcache_service.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_browser_context.h"
-#include "storage/browser/test/mock_special_storage_policy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-namespace {
-const base::FilePath::CharType kTestingAppCacheDirname[] =
-    FILE_PATH_LITERAL("Application Cache");
-
-// Examples of a protected and an unprotected origin, to be used througout the
-// test.
-const char kProtectedManifest[] = "http://www.protected.com/cache.manifest";
-const char kNormalManifest[] = "http://www.normal.com/cache.manifest";
-const char kSessionOnlyManifest[] = "http://www.sessiononly.com/cache.manifest";
-
-}  // namespace
-
-class ChromeAppCacheServiceTest : public testing::Test {
- public:
-  ChromeAppCacheServiceTest()
-      : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
-        kProtectedManifestURL(kProtectedManifest),
-        kNormalManifestURL(kNormalManifest),
-        kSessionOnlyManifestURL(kSessionOnlyManifest) {}
-
- protected:
-  scoped_refptr<ChromeAppCacheService> CreateAppCacheServiceImpl(
-      const base::FilePath& appcache_path,
-      bool init_storage);
-  void InsertDataIntoAppCache(ChromeAppCacheService* appcache_service);
-
-  BrowserTaskEnvironment task_environment_;
-  base::ScopedTempDir temp_dir_;
-  const GURL kProtectedManifestURL;
-  const GURL kNormalManifestURL;
-  const GURL kSessionOnlyManifestURL;
-
- private:
-  TestBrowserContext browser_context_;
-};
-
-scoped_refptr<ChromeAppCacheService>
-ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
-    const base::FilePath& appcache_path,
-    bool init_storage) {
-  auto appcache_service =
-      base::MakeRefCounted<ChromeAppCacheService>(nullptr, nullptr);
-  auto mock_policy = base::MakeRefCounted<storage::MockSpecialStoragePolicy>();
-  mock_policy->AddProtected(kProtectedManifestURL.GetOrigin());
-  mock_policy->AddSessionOnly(kSessionOnlyManifestURL.GetOrigin());
-  appcache_service->Initialize(appcache_path, &browser_context_,
-                               std::move(mock_policy));
-  // Steps needed to initialize the storage of AppCache data.
-  task_environment_.RunUntilIdle();
-  if (init_storage) {
-    AppCacheStorageImpl* storage =
-        static_cast<AppCacheStorageImpl*>(
-            appcache_service->storage());
-    storage->database_->db_connection();
-    storage->disk_cache();
-    task_environment_.RunUntilIdle();
-  }
-  return appcache_service;
-}
-
-void ChromeAppCacheServiceTest::InsertDataIntoAppCache(
-    ChromeAppCacheService* appcache_service) {
-  AppCacheTestHelper appcache_helper;
-  appcache_helper.AddGroupAndCache(appcache_service, kNormalManifestURL);
-  appcache_helper.AddGroupAndCache(appcache_service, kProtectedManifestURL);
-  appcache_helper.AddGroupAndCache(appcache_service, kSessionOnlyManifestURL);
-
-  // Verify that adding the data succeeded
-  std::set<url::Origin> origins;
-  appcache_helper.GetOriginsWithCaches(appcache_service, &origins);
-  ASSERT_EQ(3UL, origins.size());
-  ASSERT_TRUE(origins.find(url::Origin::Create(kProtectedManifestURL)) !=
-              origins.end());
-  ASSERT_TRUE(origins.find(url::Origin::Create(kNormalManifestURL)) !=
-              origins.end());
-  ASSERT_TRUE(origins.find(url::Origin::Create(kSessionOnlyManifestURL)) !=
-              origins.end());
-}
-
-TEST_F(ChromeAppCacheServiceTest, KeepOnDestruction) {
-  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  base::FilePath appcache_path =
-      temp_dir_.GetPath().Append(kTestingAppCacheDirname);
-
-  // Create a ChromeAppCacheService and insert data into it
-  scoped_refptr<ChromeAppCacheService> appcache_service =
-      CreateAppCacheServiceImpl(appcache_path, true);
-  ASSERT_TRUE(base::PathExists(appcache_path));
-  ASSERT_TRUE(base::PathExists(appcache_path.AppendASCII("Index")));
-  InsertDataIntoAppCache(appcache_service.get());
-
-  // Test: delete the ChromeAppCacheService
-  appcache_service = nullptr;
-  task_environment_.RunUntilIdle();
-
-  // Recreate the appcache (for reading the data back)
-  appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
-
-  // The directory is still there
-  ASSERT_TRUE(base::PathExists(appcache_path));
-
-  // The appcache data is also there, except the session-only origin.
-  AppCacheTestHelper appcache_helper;
-  std::set<url::Origin> origins;
-  appcache_helper.GetOriginsWithCaches(appcache_service.get(), &origins);
-  EXPECT_EQ(2UL, origins.size());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kProtectedManifestURL)) !=
-              origins.end());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kNormalManifestURL)) !=
-              origins.end());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kSessionOnlyManifestURL)) ==
-              origins.end());
-
-  // Delete and let cleanup tasks run prior to returning.
-  appcache_service = nullptr;
-  task_environment_.RunUntilIdle();
-}
-
-TEST_F(ChromeAppCacheServiceTest, SaveSessionState) {
-  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  base::FilePath appcache_path =
-      temp_dir_.GetPath().Append(kTestingAppCacheDirname);
-
-  // Create a ChromeAppCacheService and insert data into it
-  scoped_refptr<ChromeAppCacheService> appcache_service =
-      CreateAppCacheServiceImpl(appcache_path, true);
-  ASSERT_TRUE(base::PathExists(appcache_path));
-  ASSERT_TRUE(base::PathExists(appcache_path.AppendASCII("Index")));
-  InsertDataIntoAppCache(appcache_service.get());
-
-  // Save session state. This should bypass the destruction-time deletion.
-  appcache_service->set_force_keep_session_state();
-
-  // Test: delete the ChromeAppCacheService
-  appcache_service = nullptr;
-  task_environment_.RunUntilIdle();
-
-  // Recreate the appcache (for reading the data back)
-  appcache_service = CreateAppCacheServiceImpl(appcache_path, false);
-
-  // The directory is still there
-  ASSERT_TRUE(base::PathExists(appcache_path));
-
-  // No appcache data was deleted.
-  AppCacheTestHelper appcache_helper;
-  std::set<url::Origin> origins;
-  appcache_helper.GetOriginsWithCaches(appcache_service.get(), &origins);
-  EXPECT_EQ(3UL, origins.size());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kProtectedManifestURL)) !=
-              origins.end());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kNormalManifestURL)) !=
-              origins.end());
-  EXPECT_TRUE(origins.find(url::Origin::Create(kSessionOnlyManifestURL)) !=
-              origins.end());
-
-  // Delete and let cleanup tasks run prior to returning.
-  appcache_service = nullptr;
-  task_environment_.RunUntilIdle();
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/mock_appcache_policy.cc b/content/browser/appcache/mock_appcache_policy.cc
deleted file mode 100644
index 6f3e0be..0000000
--- a/content/browser/appcache/mock_appcache_policy.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/mock_appcache_policy.h"
-
-#include "base/feature_list.h"
-#include "net/cookies/site_for_cookies.h"
-#include "third_party/blink/public/common/features.h"
-#include "url/origin.h"
-
-namespace content {
-
-MockAppCachePolicy::MockAppCachePolicy()
-    : can_load_return_value_(true), can_create_return_value_(true) {
-}
-
-MockAppCachePolicy::~MockAppCachePolicy() = default;
-
-bool MockAppCachePolicy::CanLoadAppCache(
-    const GURL& manifest_url,
-    const net::SiteForCookies& site_for_cookies,
-    const absl::optional<url::Origin>& top_frame_origin) {
-  requested_manifest_url_ = manifest_url;
-  return can_load_return_value_;
-}
-
-bool MockAppCachePolicy::CanCreateAppCache(
-    const GURL& manifest_url,
-    const net::SiteForCookies& site_for_cookies,
-    const absl::optional<url::Origin>& top_frame_origin) {
-  requested_manifest_url_ = manifest_url;
-  return can_create_return_value_;
-}
-
-bool MockAppCachePolicy::IsOriginTrialRequiredForAppCache() {
-  // Ignore the force enable override preference here and just check the
-  // feature.
-  return base::FeatureList::IsEnabled(
-      blink::features::kAppCacheRequireOriginTrial);
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/mock_appcache_policy.h b/content/browser/appcache/mock_appcache_policy.h
deleted file mode 100644
index eda9aa0dc..0000000
--- a/content/browser/appcache/mock_appcache_policy.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_POLICY_H_
-#define CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_POLICY_H_
-
-#include "base/compiler_specific.h"
-#include "content/browser/appcache/appcache_policy.h"
-#include "url/gurl.h"
-
-namespace net {
-class SiteForCookies;
-}  // namespace net
-
-namespace url {
-class Origin;
-}  // namespace url
-
-namespace content {
-
-class MockAppCachePolicy : public AppCachePolicy {
- public:
-  MockAppCachePolicy();
-  virtual ~MockAppCachePolicy();
-
-  bool CanLoadAppCache(
-      const GURL& manifest_url,
-      const net::SiteForCookies& site_for_cookies,
-      const absl::optional<url::Origin>& top_frame_origin) override;
-  bool CanCreateAppCache(
-      const GURL& manifest_url,
-      const net::SiteForCookies& site_for_cookies,
-      const absl::optional<url::Origin>& top_frame_origin) override;
-  bool IsOriginTrialRequiredForAppCache() override;
-
-  bool can_load_return_value_;
-  bool can_create_return_value_;
-  GURL requested_manifest_url_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_POLICY_H_
diff --git a/content/browser/appcache/mock_appcache_service.cc b/content/browser/appcache/mock_appcache_service.cc
deleted file mode 100644
index 6505950..0000000
--- a/content/browser/appcache/mock_appcache_service.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/mock_appcache_service.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace content {
-
-static void DeferredCallCallback(net::CompletionOnceCallback callback, int rv) {
-  std::move(callback).Run(rv);
-}
-
-void MockAppCacheService::DeleteAppCachesForOrigin(
-    const url::Origin& origin,
-    net::CompletionOnceCallback callback) {
-  ++delete_called_count_;
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&DeferredCallCallback, std::move(callback),
-                                mock_delete_appcaches_for_origin_result_));
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/mock_appcache_service.h b/content/browser/appcache/mock_appcache_service.h
deleted file mode 100644
index 7e84003..0000000
--- a/content/browser/appcache/mock_appcache_service.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_SERVICE_H_
-#define CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_SERVICE_H_
-
-#include "base/compiler_specific.h"
-#include "content/browser/appcache/appcache_service_impl.h"
-#include "content/browser/appcache/mock_appcache_policy.h"
-#include "content/browser/appcache/mock_appcache_storage.h"
-#include "storage/browser/quota/quota_manager.h"
-
-namespace content {
-
-// For use by unit tests.
-class MockAppCacheService : public AppCacheServiceImpl {
- public:
-  explicit MockAppCacheService(base::WeakPtr<StoragePartitionImpl> partition)
-      : AppCacheServiceImpl(nullptr, std::move(partition)),
-        mock_delete_appcaches_for_origin_result_(net::OK),
-        delete_called_count_(0) {
-    storage_ = std::make_unique<MockAppCacheStorage>(this);
-    set_appcache_policy(&mock_policy_);
-  }
-  MockAppCacheService() : MockAppCacheService(nullptr) {}
-
-  // Just returns a canned completion code without actually
-  // removing groups and caches in our mock storage instance.
-  void DeleteAppCachesForOrigin(const url::Origin& origin,
-                                net::CompletionOnceCallback callback) override;
-
-  void set_quota_manager_proxy(storage::QuotaManagerProxy* proxy) {
-    quota_manager_proxy_ = proxy;
-  }
-
-  void set_mock_delete_appcaches_for_origin_result(int rv) {
-    mock_delete_appcaches_for_origin_result_ = rv;
-  }
-
-  int delete_called_count() const { return delete_called_count_; }
-
- private:
-  MockAppCachePolicy mock_policy_;
-
-  int mock_delete_appcaches_for_origin_result_;
-  int delete_called_count_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_SERVICE_H_
diff --git a/content/browser/appcache/mock_appcache_storage.cc b/content/browser/appcache/mock_appcache_storage.cc
deleted file mode 100644
index 46ce785..0000000
--- a/content/browser/appcache/mock_appcache_storage.cc
+++ /dev/null
@@ -1,558 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/appcache/mock_appcache_storage.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/check.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_entry.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/appcache_service_impl.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-
-// This is a quick and easy 'mock' implementation of the storage interface
-// that doesn't put anything to disk.
-//
-// We simply add an extra reference to objects when they're put in storage,
-// and remove the extra reference when they are removed from storage.
-// Responses are never really removed from the in-memory disk cache.
-// Delegate callbacks are made asyncly to appropiately mimic what will
-// happen with a real disk-backed storage impl that involves IO on a
-// background thread.
-
-namespace content {
-
-MockAppCacheStorage::MockAppCacheStorage(AppCacheServiceImpl* service)
-    : AppCacheStorage(service),
-      simulate_make_group_obsolete_failure_(false),
-      simulate_store_group_and_newest_cache_failure_(false),
-      simulate_find_main_resource_(false),
-      simulate_find_sub_resource_(false),
-      simulated_found_cache_id_(blink::mojom::kAppCacheNoCacheId),
-      simulated_found_group_id_(0),
-      simulated_found_network_namespace_(false) {
-  last_cache_id_ = 0;
-  last_group_id_ = 0;
-  last_response_id_ = 0;
-}
-
-MockAppCacheStorage::~MockAppCacheStorage() = default;
-
-void MockAppCacheStorage::GetAllInfo(Delegate* delegate) {
-  ScheduleTask(base::BindOnce(
-      &MockAppCacheStorage::ProcessGetAllInfo, weak_factory_.GetWeakPtr(),
-      base::WrapRefCounted(GetOrCreateDelegateReference(delegate))));
-}
-
-void MockAppCacheStorage::LoadCache(int64_t id, Delegate* delegate) {
-  DCHECK(delegate);
-  AppCache* cache = working_set_.GetCache(id);
-  if (ShouldCacheLoadAppearAsync(cache)) {
-    ScheduleTask(base::BindOnce(
-        &MockAppCacheStorage::ProcessLoadCache, weak_factory_.GetWeakPtr(), id,
-        base::WrapRefCounted(GetOrCreateDelegateReference(delegate))));
-    return;
-  }
-  ProcessLoadCache(id, GetOrCreateDelegateReference(delegate));
-}
-
-void MockAppCacheStorage::LoadOrCreateGroup(
-    const GURL& manifest_url, Delegate* delegate) {
-  DCHECK(delegate);
-  AppCacheGroup* group = working_set_.GetGroup(manifest_url);
-  if (ShouldGroupLoadAppearAsync(group)) {
-    ScheduleTask(base::BindOnce(
-        &MockAppCacheStorage::ProcessLoadOrCreateGroup,
-        weak_factory_.GetWeakPtr(), manifest_url,
-        base::WrapRefCounted(GetOrCreateDelegateReference(delegate))));
-    return;
-  }
-  ProcessLoadOrCreateGroup(
-      manifest_url, GetOrCreateDelegateReference(delegate));
-}
-
-void MockAppCacheStorage::StoreGroupAndNewestCache(
-    AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) {
-  DCHECK(group && delegate && newest_cache);
-
-  // Always make this operation look async.
-  ScheduleTask(base::BindOnce(
-      &MockAppCacheStorage::ProcessStoreGroupAndNewestCache,
-      weak_factory_.GetWeakPtr(), base::WrapRefCounted(group),
-      base::WrapRefCounted(newest_cache),
-      base::WrapRefCounted(GetOrCreateDelegateReference(delegate))));
-}
-
-void MockAppCacheStorage::FindResponseForMainRequest(
-    const GURL& url, const GURL& preferred_manifest_url, Delegate* delegate) {
-  DCHECK(delegate);
-
-  // Note: MockAppCacheStorage does not respect the preferred_manifest_url.
-
-  // Always make this operation look async.
-  ScheduleTask(base::BindOnce(
-      &MockAppCacheStorage::ProcessFindResponseForMainRequest,
-      weak_factory_.GetWeakPtr(), url,
-      base::WrapRefCounted(GetOrCreateDelegateReference(delegate))));
-}
-
-void MockAppCacheStorage::FindResponseForSubRequest(
-    AppCache* cache, const GURL& url,
-    AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
-    bool* found_network_namespace) {
-  DCHECK(cache && cache->is_complete());
-
-  // This layer of indirection is here to facilitate testing.
-  if (simulate_find_sub_resource_) {
-    *found_entry = simulated_found_entry_;
-    *found_fallback_entry = simulated_found_fallback_entry_;
-    *found_network_namespace = simulated_found_network_namespace_;
-    simulate_find_sub_resource_ = false;
-    return;
-  }
-
-  GURL fallback_namespace_not_used;
-  GURL intercept_namespace_not_used;
-  cache->FindResponseForRequest(
-      url, found_entry, &intercept_namespace_not_used,
-      found_fallback_entry,  &fallback_namespace_not_used,
-      found_network_namespace);
-}
-
-void MockAppCacheStorage::MarkEntryAsForeign(const GURL& entry_url,
-                                             int64_t cache_id) {
-  AppCache* cache = working_set_.GetCache(cache_id);
-  if (cache) {
-    AppCacheEntry* entry = cache->GetEntry(entry_url);
-    DCHECK(entry);
-    if (entry)
-      entry->add_types(AppCacheEntry::FOREIGN);
-  }
-}
-
-void MockAppCacheStorage::MakeGroupObsolete(AppCacheGroup* group,
-                                            Delegate* delegate,
-                                            int response_code) {
-  DCHECK(group && delegate);
-
-  // Always make this method look async.
-  ScheduleTask(base::BindOnce(
-      &MockAppCacheStorage::ProcessMakeGroupObsolete,
-      weak_factory_.GetWeakPtr(), base::WrapRefCounted(group),
-      base::WrapRefCounted(GetOrCreateDelegateReference(delegate)),
-      response_code));
-}
-
-void MockAppCacheStorage::StoreEvictionTimes(AppCacheGroup* group) {
-  stored_eviction_times_[group->group_id()] =
-      std::make_pair(group->last_full_update_check_time(),
-                     group->first_evictable_error_time());
-}
-
-std::unique_ptr<AppCacheResponseReader>
-MockAppCacheStorage::CreateResponseReader(const GURL& manifest_url,
-                                          int64_t response_id) {
-  if (simulated_reader_)
-    return std::move(simulated_reader_);
-  return std::make_unique<AppCacheResponseReader>(response_id,
-                                                  disk_cache()->GetWeakPtr());
-}
-
-std::unique_ptr<AppCacheResponseWriter>
-MockAppCacheStorage::CreateResponseWriter(const GURL& manifest_url) {
-  return std::make_unique<AppCacheResponseWriter>(NewResponseId(),
-                                                  disk_cache()->GetWeakPtr());
-}
-
-std::unique_ptr<AppCacheResponseMetadataWriter>
-MockAppCacheStorage::CreateResponseMetadataWriter(int64_t response_id) {
-  return std::make_unique<AppCacheResponseMetadataWriter>(
-      response_id, disk_cache()->GetWeakPtr());
-}
-
-void MockAppCacheStorage::DoomResponses(
-    const GURL& manifest_url,
-    const std::vector<int64_t>& response_ids) {
-  DeleteResponses(manifest_url, response_ids);
-}
-
-void MockAppCacheStorage::DeleteResponses(
-    const GURL& manifest_url,
-    const std::vector<int64_t>& response_ids) {
-  // We don't bother with actually removing responses from the disk-cache,
-  // just keep track of which ids have been doomed or deleted
-  for (const auto& id : response_ids)
-    doomed_response_ids_.insert(id);
-}
-
-bool MockAppCacheStorage::IsInitialized() {
-  return false;
-}
-
-void MockAppCacheStorage::ProcessGetAllInfo(
-    scoped_refptr<DelegateReference> delegate_ref) {
-  if (delegate_ref->delegate)
-    delegate_ref->delegate->OnAllInfo(simulated_appcache_info_.get());
-}
-
-void MockAppCacheStorage::ProcessLoadCache(
-    int64_t id,
-    scoped_refptr<DelegateReference> delegate_ref) {
-  AppCache* cache = working_set_.GetCache(id);
-  if (delegate_ref->delegate)
-    delegate_ref->delegate->OnCacheLoaded(cache, id);
-}
-
-void MockAppCacheStorage::ProcessLoadOrCreateGroup(
-    const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref) {
-  scoped_refptr<AppCacheGroup> group(working_set_.GetGroup(manifest_url));
-
-  // Newly created groups are not put in the stored_groups collection
-  // until StoreGroupAndNewestCache is called.
-  if (!group.get()) {
-    group = base::MakeRefCounted<AppCacheGroup>(service_->storage(),
-                                                manifest_url, NewGroupId());
-  }
-
-  if (delegate_ref->delegate)
-    delegate_ref->delegate->OnGroupLoaded(group.get(), manifest_url);
-}
-
-void MockAppCacheStorage::ProcessStoreGroupAndNewestCache(
-    scoped_refptr<AppCacheGroup> group,
-    scoped_refptr<AppCache> newest_cache,
-    scoped_refptr<DelegateReference> delegate_ref) {
-  Delegate* delegate = delegate_ref->delegate;
-  if (simulate_store_group_and_newest_cache_failure_) {
-    if (delegate)
-      delegate->OnGroupAndNewestCacheStored(
-          group.get(), newest_cache.get(), false, false);
-    return;
-  }
-
-  AddStoredGroup(group.get());
-  if (newest_cache.get() != group->newest_complete_cache()) {
-    newest_cache->set_complete(true);
-    group->AddCache(newest_cache.get());
-    AddStoredCache(newest_cache.get());
-
-    // Copy the collection prior to removal, on final release
-    // of a cache the group's collection will change.
-    std::vector<AppCache*> copy = group->old_caches();
-    RemoveStoredCaches(copy);
-  }
-
-  if (delegate)
-    delegate->OnGroupAndNewestCacheStored(
-        group.get(), newest_cache.get(), true, false);
-}
-
-namespace {
-
-struct FoundCandidate {
-  GURL namespace_entry_url;
-  AppCacheEntry entry;
-  int64_t cache_id;
-  int64_t group_id;
-  GURL manifest_url;
-  bool is_cache_in_use;
-
-  FoundCandidate()
-      : cache_id(blink::mojom::kAppCacheNoCacheId),
-        group_id(0),
-        is_cache_in_use(false) {}
-};
-
-void MaybeTakeNewNamespaceEntry(
-    AppCacheNamespaceType namespace_type,
-    const AppCacheEntry &entry,
-    const GURL& namespace_url,
-    bool cache_is_in_use,
-    FoundCandidate* best_candidate,
-    GURL* best_candidate_namespace,
-    AppCache* cache,
-    AppCacheGroup* group) {
-  DCHECK(entry.has_response_id());
-
-  bool take_new_entry = true;
-
-  // Does the new candidate entry trump our current best candidate?
-  if (best_candidate->entry.has_response_id()) {
-    // Longer namespace prefix matches win.
-    size_t candidate_length =
-        namespace_url.spec().length();
-    size_t best_length =
-        best_candidate_namespace->spec().length();
-
-    if (candidate_length > best_length) {
-      take_new_entry = true;
-    } else if (candidate_length == best_length &&
-               cache_is_in_use && !best_candidate->is_cache_in_use) {
-      take_new_entry = true;
-    } else {
-      take_new_entry = false;
-    }
-  }
-
-  if (take_new_entry) {
-    if (namespace_type == APPCACHE_FALLBACK_NAMESPACE) {
-      best_candidate->namespace_entry_url =
-          cache->GetFallbackEntryUrl(namespace_url);
-    } else {
-      best_candidate->namespace_entry_url =
-          cache->GetInterceptEntryUrl(namespace_url);
-    }
-    best_candidate->entry = entry;
-    best_candidate->cache_id = cache->cache_id();
-    best_candidate->group_id = group->group_id();
-    best_candidate->manifest_url = group->manifest_url();
-    best_candidate->is_cache_in_use = cache_is_in_use;
-    *best_candidate_namespace = namespace_url;
-  }
-}
-}  // namespace
-
-void MockAppCacheStorage::ProcessFindResponseForMainRequest(
-    const GURL& url, scoped_refptr<DelegateReference> delegate_ref) {
-  if (simulate_find_main_resource_) {
-    simulate_find_main_resource_ = false;
-    if (delegate_ref->delegate) {
-      delegate_ref->delegate->OnMainResponseFound(
-          url, simulated_found_entry_,
-          simulated_found_fallback_url_, simulated_found_fallback_entry_,
-          simulated_found_cache_id_, simulated_found_group_id_,
-          simulated_found_manifest_url_);
-    }
-    return;
-  }
-
-  // This call has no persistent side effects, if the delegate has gone
-  // away, we can just bail out early.
-  if (!delegate_ref->delegate)
-    return;
-
-  // TODO(michaeln): The heuristics around choosing amoungst
-  // multiple candidates is under specified, and just plain
-  // not fully understood. Refine these over time. In particular,
-  // * prefer candidates from newer caches
-  // * take into account the cache associated with the document
-  //   that initiated the navigation
-  // * take into account the cache associated with the document
-  //   currently residing in the frame being navigated
-  FoundCandidate found_candidate;
-  GURL found_intercept_candidate_namespace;
-  FoundCandidate found_fallback_candidate;
-  GURL found_fallback_candidate_namespace;
-
-  for (const auto& pair : stored_groups_) {
-    AppCacheGroup* group = pair.second.get();
-    AppCache* cache = group->newest_complete_cache();
-    if (group->is_obsolete() || !cache ||
-        (url.GetOrigin() != group->manifest_url().GetOrigin())) {
-      continue;
-    }
-
-    AppCacheEntry found_entry;
-    AppCacheEntry found_fallback_entry;
-    GURL found_intercept_namespace;
-    GURL found_fallback_namespace;
-    bool ignore_found_network_namespace = false;
-    bool found = cache->FindResponseForRequest(
-                            url, &found_entry, &found_intercept_namespace,
-                            &found_fallback_entry, &found_fallback_namespace,
-                            &ignore_found_network_namespace);
-
-    // 6.11.1 Navigating across documents, Step 10.
-    // Network namespacing doesn't apply to main resource loads,
-    // and foreign entries are excluded.
-    if (!found || ignore_found_network_namespace ||
-        (found_entry.has_response_id() && found_entry.IsForeign()) ||
-        (found_fallback_entry.has_response_id() &&
-         found_fallback_entry.IsForeign())) {
-      continue;
-    }
-
-    // We have a bias for hits from caches that are in use.
-    bool is_in_use = IsCacheStored(cache) && !cache->HasOneRef();
-
-    if (found_entry.has_response_id() &&
-        found_intercept_namespace.is_empty()) {
-      found_candidate.namespace_entry_url = GURL();
-      found_candidate.entry = found_entry;
-      found_candidate.cache_id = cache->cache_id();
-      found_candidate.group_id = group->group_id();
-      found_candidate.manifest_url = group->manifest_url();
-      found_candidate.is_cache_in_use = is_in_use;
-      if (is_in_use)
-        break;  // We break out of the loop with this direct hit.
-    } else if (found_entry.has_response_id() &&
-               !found_intercept_namespace.is_empty()) {
-      MaybeTakeNewNamespaceEntry(
-          APPCACHE_INTERCEPT_NAMESPACE,
-          found_entry, found_intercept_namespace, is_in_use,
-          &found_candidate, &found_intercept_candidate_namespace,
-          cache, group);
-    } else {
-      DCHECK(found_fallback_entry.has_response_id());
-      MaybeTakeNewNamespaceEntry(
-          APPCACHE_FALLBACK_NAMESPACE,
-          found_fallback_entry, found_fallback_namespace, is_in_use,
-          &found_fallback_candidate, &found_fallback_candidate_namespace,
-          cache, group);
-    }
-  }
-
-  // Found a direct hit or an intercept namespace hit.
-  if (found_candidate.entry.has_response_id()) {
-    delegate_ref->delegate->OnMainResponseFound(
-        url, found_candidate.entry, found_candidate.namespace_entry_url,
-        AppCacheEntry(),  found_candidate.cache_id, found_candidate.group_id,
-        found_candidate.manifest_url);
-    return;
-  }
-
-  // Found a fallback namespace.
-  if (found_fallback_candidate.entry.has_response_id()) {
-    delegate_ref->delegate->OnMainResponseFound(
-        url, AppCacheEntry(),
-        found_fallback_candidate.namespace_entry_url,
-        found_fallback_candidate.entry,
-        found_fallback_candidate.cache_id,
-        found_fallback_candidate.group_id,
-        found_fallback_candidate.manifest_url);
-    return;
-  }
-
-  // Didn't find anything.
-  delegate_ref->delegate->OnMainResponseFound(
-      url, AppCacheEntry(), GURL(), AppCacheEntry(),
-      blink::mojom::kAppCacheNoCacheId, 0, GURL());
-}
-
-void MockAppCacheStorage::ProcessMakeGroupObsolete(
-    scoped_refptr<AppCacheGroup> group,
-    scoped_refptr<DelegateReference> delegate_ref,
-    int response_code) {
-  if (simulate_make_group_obsolete_failure_) {
-    if (delegate_ref->delegate)
-      delegate_ref->delegate->OnGroupMadeObsolete(
-          group.get(), false, response_code);
-    return;
-  }
-
-  RemoveStoredGroup(group.get());
-  if (group->newest_complete_cache())
-    RemoveStoredCache(group->newest_complete_cache());
-
-  // Copy the collection prior to removal, on final release
-  // of a cache the group's collection will change.
-  std::vector<AppCache*> copy = group->old_caches();
-  RemoveStoredCaches(copy);
-
-  group->set_obsolete(true);
-
-  // Also remove from the working set, caches for an 'obsolete' group
-  // may linger in use, but the group itself cannot be looked up by
-  // 'manifest_url' in the working set any longer.
-  working_set()->RemoveGroup(group.get());
-
-  if (delegate_ref->delegate)
-    delegate_ref->delegate->OnGroupMadeObsolete(
-        group.get(), true, response_code);
-}
-
-void MockAppCacheStorage::ScheduleTask(base::OnceClosure task) {
-  pending_tasks_.push_back(std::move(task));
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&MockAppCacheStorage::RunOnePendingTask,
-                                weak_factory_.GetWeakPtr()));
-}
-
-void MockAppCacheStorage::RunOnePendingTask() {
-  DCHECK(!pending_tasks_.empty());
-  base::OnceClosure task = std::move(pending_tasks_.front());
-  pending_tasks_.pop_front();
-  std::move(task).Run();
-}
-
-void MockAppCacheStorage::AddStoredCache(AppCache* cache) {
-  int64_t cache_id = cache->cache_id();
-  if (stored_caches_.find(cache_id) == stored_caches_.end()) {
-    stored_caches_.insert(
-        StoredCacheMap::value_type(cache_id, base::WrapRefCounted(cache)));
-  }
-}
-
-void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) {
-  // Do not remove from the working set, active caches are still usable
-  // and may be looked up by id until they fall out of use.
-  stored_caches_.erase(cache->cache_id());
-}
-
-void MockAppCacheStorage::RemoveStoredCaches(
-    const std::vector<AppCache*>& caches) {
-  for (AppCache* cache : caches)
-    RemoveStoredCache(cache);
-}
-
-void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) {
-  const GURL& url = group->manifest_url();
-  if (stored_groups_.find(url) == stored_groups_.end()) {
-    stored_groups_.insert(
-        StoredGroupMap::value_type(url, base::WrapRefCounted(group)));
-  }
-}
-
-void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) {
-  stored_groups_.erase(group->manifest_url());
-}
-
-bool MockAppCacheStorage::ShouldGroupLoadAppearAsync(
-    const AppCacheGroup* group) {
-  // We'll have to query the database to see if a group for the
-  // manifest_url exists on disk. So return true for async.
-  if (!group)
-    return true;
-
-  // Groups without a newest cache can't have been put to disk yet, so
-  // we can synchronously return a reference we have in the working set.
-  if (!group->newest_complete_cache())
-    return false;
-
-  // The LoadGroup interface implies also loading the newest cache, so
-  // if loading the newest cache should appear async, so too must the
-  // loading of this group.
-  if (!ShouldCacheLoadAppearAsync(group->newest_complete_cache()))
-    return false;
-
-
-  // If any of the old caches are "in use", then the group must also
-  // be memory resident and not require async loading.
-  for (const AppCache* cache : group->old_caches()) {
-    // "in use" caches don't require async loading
-    if (!ShouldCacheLoadAppearAsync(cache))
-      return false;
-  }
-
-  return true;
-}
-
-bool MockAppCacheStorage::ShouldCacheLoadAppearAsync(const AppCache* cache) {
-  if (!cache)
-    return true;
-
-  // If the 'stored' ref is the only ref, real storage will have to load from
-  // the database.
-  return IsCacheStored(cache) && cache->HasOneRef();
-}
-
-}  // namespace content
diff --git a/content/browser/appcache/mock_appcache_storage.h b/content/browser/appcache/mock_appcache_storage.h
deleted file mode 100644
index 58d0e2d..0000000
--- a/content/browser/appcache/mock_appcache_storage.h
+++ /dev/null
@@ -1,257 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_STORAGE_H_
-#define CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_STORAGE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <unordered_map>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/containers/circular_deque.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_disk_cache.h"
-#include "content/browser/appcache/appcache_disk_cache_ops.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_storage.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom-forward.h"
-
-namespace content {
-FORWARD_DECLARE_TEST(AppCacheServiceImplTest, DeleteAppCachesForOrigin);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, BasicFindMainResponse);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest,
-                     BasicFindMainFallbackResponse);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, CreateGroup);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, FindMainResponseExclusions);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest,
-                     FindMainResponseWithMultipleCandidates);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, LoadCache_FarHit);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, LoadGroupAndCache_FarHit);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, MakeGroupObsolete);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, StoreNewGroup);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest, StoreExistingGroup);
-FORWARD_DECLARE_TEST(MockAppCacheStorageTest,
-                     StoreExistingGroupExistingCache);
-class AppCacheRequestHandlerTest;
-class AppCacheServiceImplTest;
-class MockAppCacheStorageTest;
-
-namespace appcache_update_job_unittest {
-class AppCacheUpdateJobTest;
-}
-
-// For use in unit tests.
-// Note: This class is also being used to bootstrap our development efforts.
-// We can get web tests up and running, and back fill with real storage
-// somewhat in parallel.
-class MockAppCacheStorage : public AppCacheStorage {
- public:
-  explicit MockAppCacheStorage(AppCacheServiceImpl* service);
-  ~MockAppCacheStorage() override;
-
-  void GetAllInfo(Delegate* delegate) override;
-  void LoadCache(int64_t id, Delegate* delegate) override;
-  void LoadOrCreateGroup(const GURL& manifest_url, Delegate* delegate) override;
-  void StoreGroupAndNewestCache(AppCacheGroup* group,
-                                AppCache* newest_cache,
-                                Delegate* delegate) override;
-  void FindResponseForMainRequest(const GURL& url,
-                                  const GURL& preferred_manifest_url,
-                                  Delegate* delegate) override;
-  void FindResponseForSubRequest(AppCache* cache,
-                                 const GURL& url,
-                                 AppCacheEntry* found_entry,
-                                 AppCacheEntry* found_fallback_entry,
-                                 bool* found_network_namespace) override;
-  void MarkEntryAsForeign(const GURL& entry_url, int64_t cache_id) override;
-  void MakeGroupObsolete(AppCacheGroup* group,
-                         Delegate* delegate,
-                         int response_code) override;
-  void StoreEvictionTimes(AppCacheGroup* group) override;
-  std::unique_ptr<AppCacheResponseReader> CreateResponseReader(
-      const GURL& manifest_url,
-      int64_t response_id) override;
-  std::unique_ptr<AppCacheResponseWriter> CreateResponseWriter(
-      const GURL& manifest_url) override;
-  std::unique_ptr<AppCacheResponseMetadataWriter> CreateResponseMetadataWriter(
-      int64_t response_id) override;
-  void DoomResponses(const GURL& manifest_url,
-                     const std::vector<int64_t>& response_ids) override;
-  void DeleteResponses(const GURL& manifest_url,
-                       const std::vector<int64_t>& response_ids) override;
-  bool IsInitialized() override;
-
- private:
-  friend class AppCacheRequestHandlerTest;
-  friend class AppCacheServiceImplTest;
-  friend class appcache_update_job_unittest::AppCacheUpdateJobTest;
-  friend class MockAppCacheStorageTest;
-
-  using StoredCacheMap = std::unordered_map<int64_t, scoped_refptr<AppCache>>;
-  using StoredGroupMap = std::map<GURL, scoped_refptr<AppCacheGroup>>;
-  using DoomedResponseIds = std::set<int64_t>;
-  using StoredEvictionTimesMap =
-      std::map<int64_t, std::pair<base::Time, base::Time>>;
-
-  void ProcessGetAllInfo(scoped_refptr<DelegateReference> delegate_ref);
-  void ProcessLoadCache(int64_t id,
-                        scoped_refptr<DelegateReference> delegate_ref);
-  void ProcessLoadOrCreateGroup(
-      const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref);
-  void ProcessStoreGroupAndNewestCache(
-      scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> newest_cache,
-      scoped_refptr<DelegateReference> delegate_ref);
-  void ProcessMakeGroupObsolete(scoped_refptr<AppCacheGroup> group,
-                                scoped_refptr<DelegateReference> delegate_ref,
-                                int response_code);
-  void ProcessFindResponseForMainRequest(
-      const GURL& url, scoped_refptr<DelegateReference> delegate_ref);
-
-  void ScheduleTask(base::OnceClosure task);
-  void RunOnePendingTask();
-
-  void AddStoredCache(AppCache* cache);
-  void RemoveStoredCache(AppCache* cache);
-  void RemoveStoredCaches(const std::vector<AppCache*>& caches);
-  bool IsCacheStored(const AppCache* cache) {
-    return stored_caches_.find(cache->cache_id()) != stored_caches_.end();
-  }
-
-  void AddStoredGroup(AppCacheGroup* group);
-  void RemoveStoredGroup(AppCacheGroup* group);
-  bool IsGroupStored(const AppCacheGroup* group) {
-    return IsGroupForManifestStored(group->manifest_url());
-  }
-  bool IsGroupForManifestStored(const GURL& manifest_url) {
-    return stored_groups_.find(manifest_url) != stored_groups_.end();
-  }
-
-  // These helpers determine when certain operations should complete
-  // asynchronously vs synchronously to faithfully mimic, or mock,
-  // the behavior of the real implemenation of the AppCacheStorage
-  // interface.
-  bool ShouldGroupLoadAppearAsync(const AppCacheGroup* group);
-  bool ShouldCacheLoadAppearAsync(const AppCache* cache);
-
-  // Lazily constructed in-memory disk cache.
-  AppCacheDiskCache* disk_cache() {
-    if (!disk_cache_) {
-      const int kMaxCacheSize = 10 * 1024 * 1024;
-      disk_cache_ = std::make_unique<AppCacheDiskCache>();
-      disk_cache_->InitWithMemBackend(kMaxCacheSize,
-                                      net::CompletionOnceCallback());
-    }
-    return disk_cache_.get();
-  }
-
-  // Simulate failures for testing. Once set all subsequent calls
-  // to MakeGroupObsolete or StorageGroupAndNewestCache will fail.
-  void SimulateMakeGroupObsoleteFailure() {
-    simulate_make_group_obsolete_failure_ = true;
-  }
-  void SimulateStoreGroupAndNewestCacheFailure() {
-    simulate_store_group_and_newest_cache_failure_ = true;
-  }
-
-  // Simulate FindResponseFor results for testing. These
-  // provided values will be return on the next call to
-  // the corresponding Find method, subsequent calls are
-  // unaffected.
-  void SimulateFindMainResource(const AppCacheEntry& entry,
-                                const GURL& fallback_url,
-                                const AppCacheEntry& fallback_entry,
-                                int64_t cache_id,
-                                int64_t group_id,
-                                const GURL& manifest_url) {
-    simulate_find_main_resource_ = true;
-    simulate_find_sub_resource_ = false;
-    simulated_found_entry_ = entry;
-    simulated_found_fallback_url_ = fallback_url;
-    simulated_found_fallback_entry_ = fallback_entry;
-    simulated_found_cache_id_ = cache_id;
-    simulated_found_group_id_ = group_id;
-    simulated_found_manifest_url_ = manifest_url,
-    simulated_found_network_namespace_ = false;  // N/A to main resource loads
-  }
-  void SimulateFindSubResource(
-      const AppCacheEntry& entry,
-      const AppCacheEntry& fallback_entry,
-      bool network_namespace) {
-    simulate_find_main_resource_ = false;
-    simulate_find_sub_resource_ = true;
-    simulated_found_entry_ = entry;
-    simulated_found_fallback_entry_ = fallback_entry;
-    simulated_found_cache_id_ =
-        blink::mojom::kAppCacheNoCacheId;    // N/A to sub resource loads
-    simulated_found_manifest_url_ = GURL();  // N/A to sub resource loads
-    simulated_found_group_id_ = 0;  // N/A to sub resource loads
-    simulated_found_network_namespace_ = network_namespace;
-  }
-
-  void SimulateGetAllInfo(scoped_refptr<AppCacheInfoCollection> info) {
-    simulated_appcache_info_ = std::move(info);
-  }
-
-  void SimulateResponseReader(std::unique_ptr<AppCacheResponseReader> reader) {
-    simulated_reader_ = std::move(reader);
-  }
-
-  StoredCacheMap stored_caches_;
-  StoredGroupMap stored_groups_;
-  StoredEvictionTimesMap stored_eviction_times_;
-  DoomedResponseIds doomed_response_ids_;
-  std::unique_ptr<AppCacheDiskCache> disk_cache_;
-  base::circular_deque<base::OnceClosure> pending_tasks_;
-
-  bool simulate_make_group_obsolete_failure_;
-  bool simulate_store_group_and_newest_cache_failure_;
-
-  bool simulate_find_main_resource_;
-  bool simulate_find_sub_resource_;
-  AppCacheEntry simulated_found_entry_;
-  AppCacheEntry simulated_found_fallback_entry_;
-  int64_t simulated_found_cache_id_;
-  int64_t simulated_found_group_id_;
-  GURL simulated_found_fallback_url_;
-  GURL simulated_found_manifest_url_;
-  bool simulated_found_network_namespace_;
-  scoped_refptr<AppCacheInfoCollection> simulated_appcache_info_;
-  std::unique_ptr<AppCacheResponseReader> simulated_reader_;
-
-  base::WeakPtrFactory<MockAppCacheStorage> weak_factory_{this};
-
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           BasicFindMainResponse);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           BasicFindMainFallbackResponse);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, CreateGroup);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           FindMainResponseExclusions);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           FindMainResponseWithMultipleCandidates);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, LoadCache_FarHit);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           LoadGroupAndCache_FarHit);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, MakeGroupObsolete);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest, StoreNewGroup);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           StoreExistingGroup);
-  FRIEND_TEST_ALL_PREFIXES(MockAppCacheStorageTest,
-                           StoreExistingGroupExistingCache);
-  FRIEND_TEST_ALL_PREFIXES(AppCacheServiceImplTest,
-                           DeleteAppCachesForOrigin);
-
-  DISALLOW_COPY_AND_ASSIGN(MockAppCacheStorage);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_APPCACHE_MOCK_APPCACHE_STORAGE_H_
diff --git a/content/browser/appcache/mock_appcache_storage_unittest.cc b/content/browser/appcache/mock_appcache_storage_unittest.cc
deleted file mode 100644
index 32483e8..0000000
--- a/content/browser/appcache/mock_appcache_storage_unittest.cc
+++ /dev/null
@@ -1,642 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/run_loop.h"
-#include "content/browser/appcache/appcache.h"
-#include "content/browser/appcache/appcache_group.h"
-#include "content/browser/appcache/appcache_response_info.h"
-#include "content/browser/appcache/appcache_storage.h"
-#include "content/browser/appcache/mock_appcache_service.h"
-#include "content/public/test/browser_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/mojom/appcache/appcache_info.mojom.h"
-
-namespace content {
-
-class MockAppCacheStorageTest : public testing::Test {
- public:
-  class MockStorageDelegate : public AppCacheStorage::Delegate {
-   public:
-    explicit MockStorageDelegate()
-        : loaded_cache_id_(0),
-          stored_group_success_(false),
-          obsoleted_success_(false),
-          found_cache_id_(blink::mojom::kAppCacheNoCacheId) {}
-
-    void OnCacheLoaded(AppCache* cache, int64_t cache_id) override {
-      loaded_cache_ = cache;
-      loaded_cache_id_ = cache_id;
-    }
-
-    void OnGroupLoaded(AppCacheGroup* group,
-                       const GURL& manifest_url) override {
-      loaded_group_ = group;
-      loaded_manifest_url_ = manifest_url;
-    }
-
-    void OnGroupAndNewestCacheStored(AppCacheGroup* group,
-                                     AppCache* newest_cache,
-                                     bool success,
-                                     bool would_exceed_quota) override {
-      stored_group_ = group;
-      stored_group_success_ = success;
-    }
-
-    void OnGroupMadeObsolete(AppCacheGroup* group,
-                             bool success,
-                             int response_code) override {
-      obsoleted_group_ = group;
-      obsoleted_success_ = success;
-    }
-
-    void OnMainResponseFound(const GURL& url,
-                             const AppCacheEntry& entry,
-                             const GURL& fallback_url,
-                             const AppCacheEntry& fallback_entry,
-                             int64_t cache_id,
-                             int64_t group_id,
-                             const GURL& manifest_url) override {
-      found_url_ = url;
-      found_entry_ = entry;
-      found_fallback_url_ = fallback_url;
-      found_fallback_entry_ = fallback_entry;
-      found_cache_id_ = cache_id;
-      found_manifest_url_ = manifest_url;
-    }
-
-    scoped_refptr<AppCache> loaded_cache_;
-    int64_t loaded_cache_id_;
-    scoped_refptr<AppCacheGroup> loaded_group_;
-    GURL loaded_manifest_url_;
-    scoped_refptr<AppCacheGroup> stored_group_;
-    bool stored_group_success_;
-    scoped_refptr<AppCacheGroup> obsoleted_group_;
-    bool obsoleted_success_;
-    GURL found_url_;
-    AppCacheEntry found_entry_;
-    GURL found_fallback_url_;
-    AppCacheEntry found_fallback_entry_;
-    int64_t found_cache_id_;
-    GURL found_manifest_url_;
-  };
-
- private:
-  content::BrowserTaskEnvironment task_environment_;
-};
-
-TEST_F(MockAppCacheStorageTest, LoadCache_Miss) {
-  // Attempt to load a cache that doesn't exist. Should
-  // complete asyncly.
-  MockAppCacheService service;
-  MockStorageDelegate delegate;
-  service.storage()->LoadCache(111, &delegate);
-  EXPECT_NE(111, delegate.loaded_cache_id_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(111, delegate.loaded_cache_id_);
-  EXPECT_FALSE(delegate.loaded_cache_.get());
-}
-
-TEST_F(MockAppCacheStorageTest, LoadCache_NearHit) {
-  // Attempt to load a cache that is currently in use
-  // and does not require loading from disk. This
-  // load should complete syncly.
-  MockAppCacheService service;
-
-  // Setup some preconditions. Make an 'unstored' cache for
-  // us to load. The ctor should put it in the working set.
-  int64_t cache_id = service.storage()->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  service.storage()->LoadCache(cache_id, &delegate);
-  EXPECT_EQ(cache_id, delegate.loaded_cache_id_);
-  EXPECT_EQ(cache.get(), delegate.loaded_cache_.get());
-}
-
-TEST_F(MockAppCacheStorageTest, CreateGroup) {
-  // Attempt to load/create a group that doesn't exist.
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-  MockStorageDelegate delegate;
-  GURL manifest_url("http://blah/");
-  service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
-  EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_FALSE(delegate.loaded_group_.get());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_TRUE(delegate.loaded_group_.get());
-  EXPECT_TRUE(delegate.loaded_group_->HasOneRef());
-  EXPECT_FALSE(delegate.loaded_group_->newest_complete_cache());
-  EXPECT_TRUE(storage->stored_groups_.empty());
-}
-
-TEST_F(MockAppCacheStorageTest, LoadGroup_NearHit) {
-  // Attempt to load a group that is currently in use
-  // and does not require loading from disk. This
-  // load should complete syncly.
-  MockAppCacheService service;
-  MockStorageDelegate delegate;
-
-  // Setup some preconditions. Create a group that appears
-  // to be "unstored" and "currently in use".
-  GURL manifest_url("http://blah/");
-  service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_TRUE(delegate.loaded_group_.get());
-
-  // Reset our delegate, and take a reference to the new group.
-  scoped_refptr<AppCacheGroup> group;
-  group.swap(delegate.loaded_group_);
-  delegate.loaded_manifest_url_ = GURL();
-
-  // Conduct the test.
-  service.storage()->LoadOrCreateGroup(manifest_url, &delegate);
-  EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_EQ(group.get(), delegate.loaded_group_.get());
-}
-
-TEST_F(MockAppCacheStorageTest, LoadGroupAndCache_FarHit) {
-  // Attempt to load a cache that is not currently in use
-  // and does require loading from disk. This
-  // load should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a group and newest cache that
-  // appears to be "stored" and "not currently in use".
-  GURL manifest_url("http://blah/");
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), manifest_url, 111);
-  int64_t cache_id = storage->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-  cache->set_complete(true);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-
-  // Drop the references from above so the only refs to these
-  // objects are from within the storage class. This is to make
-  // these objects appear as "not currently in use".
-  AppCache* cache_ptr = cache.get();
-  AppCacheGroup* group_ptr = group.get();
-  cache = nullptr;
-  group = nullptr;
-
-  // Setup a delegate to receive completion callbacks.
-  MockStorageDelegate delegate;
-
-  // Conduct the cache load test.
-  EXPECT_NE(cache_id, delegate.loaded_cache_id_);
-  EXPECT_NE(cache_ptr, delegate.loaded_cache_.get());
-  storage->LoadCache(cache_id, &delegate);
-  EXPECT_NE(cache_id, delegate.loaded_cache_id_);
-  EXPECT_NE(cache_ptr, delegate.loaded_cache_.get());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(cache_id, delegate.loaded_cache_id_);
-  EXPECT_EQ(cache_ptr, delegate.loaded_cache_.get());
-  delegate.loaded_cache_ = nullptr;
-
-  // Conduct the group load test.
-  EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_FALSE(delegate.loaded_group_.get());
-  storage->LoadOrCreateGroup(manifest_url, &delegate);
-  EXPECT_NE(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_FALSE(delegate.loaded_group_.get());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(manifest_url, delegate.loaded_manifest_url_);
-  EXPECT_EQ(group_ptr, delegate.loaded_group_.get());
-}
-
-TEST_F(MockAppCacheStorageTest, StoreNewGroup) {
-  // Store a group and its newest cache. Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a group and newest cache that
-  // appears to be "unstored".
-  GURL manifest_url("http://blah/");
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), manifest_url, 111);
-  int64_t cache_id = storage->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-  // Hold a ref to the cache simulate the UpdateJob holding that ref,
-  // and hold a ref to the group to simulate the CacheHost holding that ref.
-
-  // Conduct the store test.
-  MockStorageDelegate delegate;
-  EXPECT_TRUE(storage->stored_caches_.empty());
-  EXPECT_TRUE(storage->stored_groups_.empty());
-  storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate);
-  EXPECT_FALSE(delegate.stored_group_success_);
-  EXPECT_TRUE(storage->stored_caches_.empty());
-  EXPECT_TRUE(storage->stored_groups_.empty());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_TRUE(delegate.stored_group_success_);
-  EXPECT_FALSE(storage->stored_caches_.empty());
-  EXPECT_FALSE(storage->stored_groups_.empty());
-  EXPECT_EQ(cache.get(), group->newest_complete_cache());
-  EXPECT_TRUE(cache->is_complete());
-}
-
-TEST_F(MockAppCacheStorageTest, StoreExistingGroup) {
-  // Store a group and its newest cache. Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a group and old complete cache
-  // that appear to be "stored", and a newest unstored complete cache.
-  GURL manifest_url("http://blah/");
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), manifest_url, 111);
-  int64_t old_cache_id = storage->NewCacheId();
-  auto old_cache =
-      base::MakeRefCounted<AppCache>(service.storage(), old_cache_id);
-  old_cache->set_complete(true);
-  group->AddCache(old_cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(old_cache.get());
-  int64_t new_cache_id = storage->NewCacheId();
-  auto new_cache =
-      base::MakeRefCounted<AppCache>(service.storage(), new_cache_id);
-  // Hold our refs to simulate the UpdateJob holding these refs.
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_TRUE(storage->IsCacheStored(old_cache.get()));
-  EXPECT_FALSE(storage->IsCacheStored(new_cache.get()));
-  storage->StoreGroupAndNewestCache(group.get(), new_cache.get(), &delegate);
-  EXPECT_FALSE(delegate.stored_group_success_);
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_TRUE(storage->IsCacheStored(old_cache.get()));
-  EXPECT_FALSE(storage->IsCacheStored(new_cache.get()));
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_TRUE(delegate.stored_group_success_);
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_FALSE(storage->IsCacheStored(old_cache.get()));
-  EXPECT_TRUE(storage->IsCacheStored(new_cache.get()));
-  EXPECT_EQ(new_cache.get(), group->newest_complete_cache());
-  EXPECT_TRUE(new_cache->is_complete());
-}
-
-TEST_F(MockAppCacheStorageTest, StoreExistingGroupExistingCache) {
-  // Store a group with updates to its existing newest complete cache.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a group and a complete cache that
-  // appear to be "stored".
-  GURL manifest_url("http://blah");
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), manifest_url, 111);
-  int64_t cache_id = storage->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-  cache->set_complete(true);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-  // Hold our refs to simulate the UpdateJob holding these refs.
-
-  // Change the group's newest cache.
-  EXPECT_EQ(cache.get(), group->newest_complete_cache());
-  GURL entry_url("http://blah/blah");
-  cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::MASTER));
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_TRUE(storage->IsCacheStored(cache.get()));
-  storage->StoreGroupAndNewestCache(group.get(), cache.get(), &delegate);
-  EXPECT_FALSE(delegate.stored_group_success_);
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_TRUE(delegate.stored_group_success_);
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_TRUE(storage->IsCacheStored(cache.get()));
-  EXPECT_EQ(cache.get(), group->newest_complete_cache());
-  EXPECT_TRUE(cache->GetEntry(entry_url));
-}
-
-TEST_F(MockAppCacheStorageTest, MakeGroupObsolete) {
-  // Make a group obsolete, should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a group and newest cache that
-  // appears to be "stored" and "currently in use".
-  GURL manifest_url("http://blah/");
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), manifest_url, 111);
-  int64_t cache_id = storage->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-  cache->set_complete(true);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-  // Hold our refs to simulate the UpdateJob holding these refs.
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_FALSE(group->is_obsolete());
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_FALSE(cache->HasOneRef());
-  EXPECT_FALSE(group->HasOneRef());
-  storage->MakeGroupObsolete(group.get(), &delegate, 0);
-  EXPECT_FALSE(group->is_obsolete());
-  EXPECT_EQ(size_t(1), storage->stored_caches_.size());
-  EXPECT_EQ(size_t(1), storage->stored_groups_.size());
-  EXPECT_FALSE(cache->HasOneRef());
-  EXPECT_FALSE(group->HasOneRef());
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_TRUE(delegate.obsoleted_success_);
-  EXPECT_EQ(group.get(), delegate.obsoleted_group_.get());
-  EXPECT_TRUE(group->is_obsolete());
-  EXPECT_TRUE(storage->stored_caches_.empty());
-  EXPECT_TRUE(storage->stored_groups_.empty());
-  EXPECT_TRUE(cache->HasOneRef());
-  EXPECT_FALSE(group->HasOneRef());
-  delegate.obsoleted_group_ = nullptr;
-  cache = nullptr;
-  EXPECT_TRUE(group->HasOneRef());
-}
-
-TEST_F(MockAppCacheStorageTest, MarkEntryAsForeign) {
-  // Should complete syncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a cache with an entry.
-  GURL entry_url("http://blah/entry");
-  int64_t cache_id = storage->NewCacheId();
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), cache_id);
-  cache->AddEntry(entry_url, AppCacheEntry(AppCacheEntry::EXPLICIT));
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_FALSE(cache->GetEntry(entry_url)->IsForeign());
-  storage->MarkEntryAsForeign(entry_url, cache_id);
-  EXPECT_TRUE(cache->GetEntry(entry_url)->IsForeign());
-  EXPECT_TRUE(cache->GetEntry(entry_url)->IsExplicit());
-}
-
-TEST_F(MockAppCacheStorageTest, FindNoMainResponse) {
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  GURL url("http://blah/some_url");
-  EXPECT_NE(url, delegate.found_url_);
-  storage->FindResponseForMainRequest(url, GURL(), &delegate);
-  EXPECT_NE(url, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(url, delegate.found_url_);
-  EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, delegate.found_cache_id_);
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_entry_.response_id());
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_fallback_entry_.response_id());
-  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
-  EXPECT_EQ(0, delegate.found_entry_.types());
-  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
-}
-
-TEST_F(MockAppCacheStorageTest, BasicFindMainResponse) {
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a complete cache with an entry.
-  const int64_t kCacheId = storage->NewCacheId();
-  const GURL kEntryUrl("http://blah/entry");
-  const GURL kManifestUrl("http://blah/manifest");
-  const int64_t kResponseId = 1;
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId);
-  cache->AddEntry(
-      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId));
-  cache->set_complete(true);
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl, 111);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(kEntryUrl, delegate.found_url_);
-  EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
-  EXPECT_EQ(kCacheId, delegate.found_cache_id_);
-  EXPECT_EQ(kResponseId, delegate.found_entry_.response_id());
-  EXPECT_TRUE(delegate.found_entry_.IsExplicit());
-  EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
-}
-
-TEST_F(MockAppCacheStorageTest, BasicFindMainFallbackResponse) {
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a complete cache with a
-  // fallback namespace and entry.
-  const int64_t kCacheId = storage->NewCacheId();
-  const GURL kFallbackEntryUrl1("http://blah/fallback_entry1");
-  const GURL kFallbackNamespaceUrl1("http://blah/fallback_namespace/");
-  const GURL kFallbackEntryUrl2("http://blah/fallback_entry2");
-  const GURL kFallbackNamespaceUrl2("http://blah/fallback_namespace/longer");
-  const GURL kManifestUrl("http://blah/manifest");
-  const int64_t kResponseId1 = 1;
-  const int64_t kResponseId2 = 2;
-
-  AppCacheManifest manifest;
-  manifest.fallback_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl1, kFallbackEntryUrl1));
-  manifest.fallback_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_FALLBACK_NAMESPACE, kFallbackNamespaceUrl2, kFallbackEntryUrl2));
-
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId);
-  cache->InitializeWithManifest(&manifest);
-  cache->AddEntry(kFallbackEntryUrl1,
-                  AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId1));
-  cache->AddEntry(kFallbackEntryUrl2,
-                  AppCacheEntry(AppCacheEntry::FALLBACK, kResponseId2));
-  cache->set_complete(true);
-
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl, 111);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-
-  // The test url is in both fallback namespace urls, but should match
-  // the longer of the two.
-  const GURL kTestUrl("http://blah/fallback_namespace/longer/test");
-
-  // Conduct the test.
-  MockStorageDelegate delegate;
-  EXPECT_NE(kTestUrl, delegate.found_url_);
-  storage->FindResponseForMainRequest(kTestUrl, GURL(), &delegate);
-  EXPECT_NE(kTestUrl, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(kTestUrl, delegate.found_url_);
-  EXPECT_EQ(kManifestUrl, delegate.found_manifest_url_);
-  EXPECT_EQ(kCacheId, delegate.found_cache_id_);
-  EXPECT_FALSE(delegate.found_entry_.has_response_id());
-  EXPECT_EQ(kResponseId2, delegate.found_fallback_entry_.response_id());
-  EXPECT_EQ(kFallbackEntryUrl2, delegate.found_fallback_url_);
-  EXPECT_TRUE(delegate.found_fallback_entry_.IsFallback());
-}
-
-TEST_F(MockAppCacheStorageTest, FindMainResponseWithMultipleCandidates) {
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create 2 complete caches with an entry
-  // for the same url.
-
-  const GURL kEntryUrl("http://blah/entry");
-  const int64_t kCacheId1 = storage->NewCacheId();
-  const int64_t kCacheId2 = storage->NewCacheId();
-  const GURL kManifestUrl1("http://blah/manifest1");
-  const GURL kManifestUrl2("http://blah/manifest2");
-  const int64_t kResponseId1 = 1;
-  const int64_t kResponseId2 = 2;
-
-  // The first cache.
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId1);
-  cache->AddEntry(
-      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId1));
-  cache->set_complete(true);
-  auto group = base::MakeRefCounted<AppCacheGroup>(service.storage(),
-                                                   kManifestUrl1, 111);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-  // Drop our references to cache1 so it appears as "not in use".
-  cache = nullptr;
-  group = nullptr;
-
-  // The second cache.
-  cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId2);
-  cache->AddEntry(
-      kEntryUrl, AppCacheEntry(AppCacheEntry::EXPLICIT, kResponseId2));
-  cache->set_complete(true);
-  group = base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl2,
-                                              222);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-
-  // Conduct the test, we should find the response from the second cache
-  // since it's "in use".
-  MockStorageDelegate delegate;
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(kEntryUrl, delegate.found_url_);
-  EXPECT_EQ(kManifestUrl2, delegate.found_manifest_url_);
-  EXPECT_EQ(kCacheId2, delegate.found_cache_id_);
-  EXPECT_EQ(kResponseId2, delegate.found_entry_.response_id());
-  EXPECT_TRUE(delegate.found_entry_.IsExplicit());
-  EXPECT_FALSE(delegate.found_fallback_entry_.has_response_id());
-}
-
-TEST_F(MockAppCacheStorageTest, FindMainResponseExclusions) {
-  // Should complete asyncly.
-  MockAppCacheService service;
-  MockAppCacheStorage* storage =
-      static_cast<MockAppCacheStorage*>(service.storage());
-
-  // Setup some preconditions. Create a complete cache with a
-  // foreign entry and an online namespace.
-
-  const int64_t kCacheId = storage->NewCacheId();
-  const GURL kEntryUrl("http://blah/entry");
-  const GURL kManifestUrl("http://blah/manifest");
-  const GURL kOnlineNamespaceUrl("http://blah/online_namespace");
-  const int64_t kResponseId = 1;
-
-  AppCacheManifest manifest;
-  manifest.online_safelist_namespaces.push_back(AppCacheNamespace(
-      APPCACHE_NETWORK_NAMESPACE, kOnlineNamespaceUrl, GURL()));
-  auto cache = base::MakeRefCounted<AppCache>(service.storage(), kCacheId);
-  cache->InitializeWithManifest(&manifest);
-  cache->AddEntry(
-      kEntryUrl,
-      AppCacheEntry(AppCacheEntry::EXPLICIT | AppCacheEntry::FOREIGN,
-                    kResponseId));
-  cache->set_complete(true);
-  auto group =
-      base::MakeRefCounted<AppCacheGroup>(service.storage(), kManifestUrl, 111);
-  group->AddCache(cache.get());
-  storage->AddStoredGroup(group.get());
-  storage->AddStoredCache(cache.get());
-
-  MockStorageDelegate delegate;
-
-  // We should not find anything for the foreign entry.
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  storage->FindResponseForMainRequest(kEntryUrl, GURL(), &delegate);
-  EXPECT_NE(kEntryUrl, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(kEntryUrl, delegate.found_url_);
-  EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, delegate.found_cache_id_);
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_entry_.response_id());
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_fallback_entry_.response_id());
-  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
-  EXPECT_EQ(0, delegate.found_entry_.types());
-  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
-
-  // We should not find anything for the online namespace.
-  EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
-  storage->FindResponseForMainRequest(kOnlineNamespaceUrl, GURL(), &delegate);
-  EXPECT_NE(kOnlineNamespaceUrl, delegate.found_url_);
-  base::RunLoop().RunUntilIdle();  // Do async task execution.
-  EXPECT_EQ(kOnlineNamespaceUrl, delegate.found_url_);
-  EXPECT_TRUE(delegate.found_manifest_url_.is_empty());
-  EXPECT_EQ(blink::mojom::kAppCacheNoCacheId, delegate.found_cache_id_);
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_entry_.response_id());
-  EXPECT_EQ(blink::mojom::kAppCacheNoResponseId,
-            delegate.found_fallback_entry_.response_id());
-  EXPECT_TRUE(delegate.found_fallback_url_.is_empty());
-  EXPECT_EQ(0, delegate.found_entry_.types());
-  EXPECT_EQ(0, delegate.found_fallback_entry_.types());
-}
-
-}  // namespace content
diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc
index 6d8c247..b7fca8a 100644
--- a/content/browser/client_hints/client_hints.cc
+++ b/content/browser/client_hints/client_hints.cc
@@ -279,11 +279,25 @@
   DCHECK(headers);
   DCHECK(context);
 
+  double overall_scale_factor =
+      GetZoomFactor(context, url) * GetDeviceScaleFactor();
   double viewport_height = (display::Screen::GetScreen()
                                 ->GetPrimaryDisplay()
                                 .GetSizeInPixel()
                                 .height()) /
-                           GetZoomFactor(context, url) / GetDeviceScaleFactor();
+                           overall_scale_factor;
+#if defined(OS_ANDROID)
+  // On Android, the viewport is scaled so the width is 980 and the height
+  // maintains the same ratio.
+  // TODO(1246208): Improve the usefulness of the viewport client hints for
+  // navigation requests.
+  double viewport_width = (display::Screen::GetScreen()
+                               ->GetPrimaryDisplay()
+                               .GetSizeInPixel()
+                               .width()) /
+                          overall_scale_factor;
+  viewport_height *= 980.0 / viewport_width;
+#endif  // OS_ANDROID
 
   DCHECK_LT(0, viewport_height);
 
diff --git a/content/browser/interest_group/interest_group_storage.cc b/content/browser/interest_group/interest_group_storage.cc
index 82cf14dd..979a04ff 100644
--- a/content/browser/interest_group/interest_group_storage.cc
+++ b/content/browser/interest_group/interest_group_storage.cc
@@ -44,22 +44,21 @@
 // Version number of the database.
 //
 // Version 1 - 2021/03 - crrev.com/c/2757425
+// Version 2 - 2021/08 - crrev.com/c/3097715
+// Version 3 - 2021/09 - crrev.com/c/3165576
 //
 // Version 1 adds a table for interest groups.
-//
-// Version 2 - 2021/08 - crrev.com/c/3097715
-//
 // Version 2 adds a column for rate limiting interest group updates.
-const int kCurrentVersionNumber = 2;
+// Version 3 adds a field for ad components.
+const int kCurrentVersionNumber = 3;
 
 // Earliest version which can use a |kCurrentVersionNumber| database
 // without failing.
-const int kCompatibleVersionNumber = 2;
+const int kCompatibleVersionNumber = 3;
 
 // Latest version of the database that cannot be upgraded to
-// |kCurrentVersionNumber| without razing the database. No versions are
-// currently deprecated.
-const int kDeprecatedVersionNumber = 1;
+// |kCurrentVersionNumber| without razing the database.
+const int kDeprecatedVersionNumber = 2;
 
 // TODO(crbug.com/1195852): Add UMA to count errors.
 }  // namespace
@@ -161,7 +160,7 @@
 
 // Initializes the tables, returning true on success.
 // The tables cannot exist when calling this function.
-bool CreateV2Schema(sql::Database& db) {
+bool CreateV3Schema(sql::Database& db) {
   DCHECK(!db.DoesTableExist("interest_groups"));
   static const char kInterestGroupTableSql[] =
       // clang-format off
@@ -177,6 +176,7 @@
         "trusted_bidding_signals_keys TEXT NOT NULL,"
         "user_bidding_signals TEXT,"
         "ads TEXT NOT NULL,"
+        "ad_components TEXT NOT NULL,"
       "PRIMARY KEY(owner,name))";
   // clang-format on
   if (!db.Execute(kInterestGroupTableSql))
@@ -286,8 +286,9 @@
             "trusted_bidding_signals_url,"
             "trusted_bidding_signals_keys,"
             "user_bidding_signals,"  // opaque data
-            "ads) "
-          "VALUES(?,?,?,?,?,?,?,?,?,?,?)"));
+            "ads,"
+            "ad_components) "
+          "VALUES(?,?,?,?,?,?,?,?,?,?,?,?)"));
   // clang-format on
   if (!join_group.is_valid())
     return false;
@@ -308,6 +309,7 @@
     join_group.BindNull(9);
   }
   join_group.BindString(10, Serialize(data.ads));
+  join_group.BindString(11, Serialize(data.ad_components));
 
   if (!join_group.Run())
     return false;
@@ -347,14 +349,20 @@
   // (bidding_url, update_url, etc.) getting written back to the field -- in
   // other words, that field doesn't change.
 
-  sql::Statement update_group(db.GetCachedStatement(SQL_FROM_HERE, R"(
-UPDATE interest_groups SET
-  last_updated=?,
-  bidding_url=COALESCE(?,bidding_url),
-  trusted_bidding_signals_url=COALESCE(?,trusted_bidding_signals_url),
-  trusted_bidding_signals_keys=COALESCE(?,trusted_bidding_signals_keys),
-  ads=COALESCE(?,ads)
-WHERE owner=? AND name=?)"));
+  // clang-format off
+  sql::Statement update_group(
+    db.GetCachedStatement(SQL_FROM_HERE,
+      "UPDATE interest_groups "
+      "SET last_updated=?,"
+          "bidding_url=COALESCE(?,bidding_url),"
+          "trusted_bidding_signals_url="
+              "COALESCE(?,trusted_bidding_signals_url),"
+          "trusted_bidding_signals_keys="
+              "COALESCE(?,trusted_bidding_signals_keys),"
+          "ads=COALESCE(?,ads),"
+          "ad_components=COALESCE(?,ad_components) "
+      "WHERE owner=? AND name=?"));
+  // clang-format on
 
   if (!update_group.is_valid())
     return false;
@@ -381,8 +389,13 @@
   } else {
     update_group.BindNull(4);
   }
-  update_group.BindString(5, Serialize(data.owner));
-  update_group.BindString(6, data.name);
+  if (data.ad_components) {
+    update_group.BindString(5, Serialize(data.ad_components));
+  } else {
+    update_group.BindNull(5);
+  }
+  update_group.BindString(6, Serialize(data.owner));
+  update_group.BindString(7, data.name);
 
   return update_group.Run();
 }
@@ -667,7 +680,8 @@
           "trusted_bidding_signals_url,"
           "trusted_bidding_signals_keys,"
           "user_bidding_signals,"  // opaque data
-          "ads "
+          "ads,"
+          "ad_components "
         "FROM interest_groups "
         "WHERE owner = ? AND expiration >=? AND ?>= next_update_after "
         "ORDER BY expiration ASC "
@@ -710,6 +724,8 @@
       interest_group->user_bidding_signals = load.ColumnString(8);
     interest_group->ads =
         DeserializeInterestGroupAdVector(load.ColumnString(9));
+    interest_group->ad_components =
+        DeserializeInterestGroupAdVector(load.ColumnString(10));
 
     bidding_interest_group->signals =
         auction_worklet::mojom::BiddingBrowserSignals::New();
@@ -984,7 +1000,7 @@
     return false;
 
   if (!db_->DoesTableExist("interest_groups")) {
-    return CreateV2Schema(*db_);
+    return CreateV3Schema(*db_);
   }
 
   sql::MetaTable meta_table;
@@ -1004,7 +1020,7 @@
     db_->Raze();
     return meta_table.Init(db_.get(), kCurrentVersionNumber,
                            kCompatibleVersionNumber) &&
-           CreateV2Schema(*db_);
+           CreateV3Schema(*db_);
   }
 
   if (meta_table.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
@@ -1016,7 +1032,7 @@
     db_->Raze();
     return meta_table.Init(db_.get(), kCurrentVersionNumber,
                            kCompatibleVersionNumber) &&
-           CreateV2Schema(*db_);
+           CreateV3Schema(*db_);
   }
 
   DCHECK(sql::MetaTable::DoesTableExist(db_.get()));
diff --git a/content/browser/interest_group/interest_group_storage_unittest.cc b/content/browser/interest_group/interest_group_storage_unittest.cc
index 60114d93..6f1678b 100644
--- a/content/browser/interest_group/interest_group_storage_unittest.cc
+++ b/content/browser/interest_group/interest_group_storage_unittest.cc
@@ -277,6 +277,11 @@
       GURL("https://full.example.com/ad1"), "metadata1"));
   full.ads->emplace_back(blink::InterestGroup::Ad(
       GURL("https://full.example.com/ad2"), "metadata2"));
+  full.ad_components.emplace();
+  full.ad_components->emplace_back(blink::InterestGroup::Ad(
+      GURL("https://full.example.com/adcomponent1"), "metadata1c"));
+  full.ad_components->emplace_back(blink::InterestGroup::Ad(
+      GURL("https://full.example.com/adcomponent2"), "metadata2c"));
 
   std::unique_ptr<InterestGroupStorage> storage = CreateStorage();
 
diff --git a/content/browser/presentation/presentation_service_impl.cc b/content/browser/presentation/presentation_service_impl.cc
index 20a0bc0c..16676f6 100644
--- a/content/browser/presentation/presentation_service_impl.cc
+++ b/content/browser/presentation/presentation_service_impl.cc
@@ -127,7 +127,7 @@
     mojo::PendingRemote<blink::mojom::PresentationController>
         presentation_controller_remote) {
   if (presentation_controller_remote_) {
-    mojo::ReportBadMessage(
+    presentation_service_receivers_.ReportBadMessage(
         "There can only be one PresentationController at any given time.");
     return;
   }
@@ -151,14 +151,15 @@
   }
 
   if (!receiver_delegate_ || !is_main_frame_) {
-    mojo::ReportBadMessage(
+    presentation_service_receivers_.ReportBadMessage(
         "SetReceiver can only be called from a "
         "presentation receiver main frame.");
     return;
   }
 
   if (presentation_receiver_remote_) {
-    mojo::ReportBadMessage("SetReceiver can only be called once.");
+    presentation_service_receivers_.ReportBadMessage(
+        "SetReceiver can only be called once.");
     return;
   }
 
diff --git a/content/browser/renderer_host/clipboard_host_impl.cc b/content/browser/renderer_host/clipboard_host_impl.cc
index 72ad189e..ad130aa 100644
--- a/content/browser/renderer_host/clipboard_host_impl.cc
+++ b/content/browser/renderer_host/clipboard_host_impl.cc
@@ -510,7 +510,7 @@
     return;
   std::vector<std::u16string> format_types =
       ui::Clipboard::GetForCurrentThread()
-          ->ReadAvailablePlatformSpecificFormatNames(
+          ->ReadAvailableStandardAndCustomFormatNames(
               ui::ClipboardBuffer::kCopyPaste, CreateDataEndpoint().get());
   std::move(callback).Run(format_types);
 }
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
index 46db0c0..3f8e2bf 100644
--- a/content/browser/renderer_host/frame_tree.cc
+++ b/content/browser/renderer_host/frame_tree.cc
@@ -435,6 +435,8 @@
       parent->AddChild(std::move(new_node), process_id, new_routing_id,
                        std::move(frame_remote), frame_token);
 
+  added_node->SetFencedFrameNonceIfNeeded();
+
   DCHECK(browser_interface_broker_receiver.is_valid());
   added_node->current_frame_host()->BindBrowserInterfaceBrokerReceiver(
       std::move(browser_interface_broker_receiver));
@@ -789,6 +791,7 @@
   root_->SetFrameName(main_frame_name, unique_name);
   root_->render_manager()->InitRoot(main_frame_site_instance,
                                     renderer_initiated_creation);
+  root_->SetFencedFrameNonceIfNeeded();
 }
 
 void FrameTree::DidAccessInitialMainDocument() {
diff --git a/content/browser/renderer_host/frame_tree_browsertest.cc b/content/browser/renderer_host/frame_tree_browsertest.cc
index 8ddd247d..9c7d226 100644
--- a/content/browser/renderer_host/frame_tree_browsertest.cc
+++ b/content/browser/renderer_host/frame_tree_browsertest.cc
@@ -1175,6 +1175,136 @@
   EXPECT_TRUE(nested_fenced_frame_root_node->IsInFencedFrameTree());
 }
 
+// Tests a nonce is correctly set in the isolation info for a fenced frame tree.
+IN_PROC_BROWSER_TEST_P(FencedFrameTreeBrowserTest, CheckIsolationInfoNonce) {
+  GURL main_url(https_server()->GetURL("a.test", "/hello.html"));
+  EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+  // It is safe to obtain the root frame tree node here, as it doesn't change.
+  FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+                            ->GetFrameTree()
+                            ->root();
+
+  EXPECT_TRUE(ExecJs(root,
+                     "var f = document.createElement('fencedframe');"
+                     "document.body.appendChild(f);"));
+  EXPECT_EQ(1U, root->child_count());
+
+  auto* fenced_frame = GetFencedFrameRootNode(root->child_at(0));
+  EXPECT_TRUE(fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(fenced_frame->IsInFencedFrameTree());
+
+  // Before we check the isolation info on the fenced frame, we must navigate it
+  // once. This is because the root of a FrameTree does not call
+  // RenderFrameHostImpl::RenderFrameCreated() on its owned RFHI.
+  {
+    // Navigate the fenced frame.
+    GURL fenced_frame_url(https_server()->GetURL("a.test", "/title1.html"));
+    std::string navigate_script =
+        JsReplace("f.src = $1;", fenced_frame_url.spec());
+    NavigateFrameInsideFencedFrameTreeAndWaitForFinishedLoad(
+        fenced_frame, fenced_frame_url, navigate_script);
+  }
+
+  // There should be a nonce in the IsolationInfo.
+  const net::IsolationInfo& isolation_info =
+      fenced_frame->current_frame_host()->GetIsolationInfoForSubresources();
+  EXPECT_TRUE(isolation_info.nonce().has_value());
+  absl::optional<base::UnguessableToken> fenced_frame_nonce =
+      fenced_frame->fenced_frame_nonce();
+  EXPECT_TRUE(fenced_frame_nonce.has_value());
+  EXPECT_EQ(fenced_frame_nonce.value(), isolation_info.nonce().value());
+
+  // Add an iframe.
+  EXPECT_TRUE(ExecJs(root,
+                     "var subframe = document.createElement('iframe');"
+                     "document.body.appendChild(subframe);"));
+  EXPECT_EQ(2U, root->child_count());
+  auto* iframe = root->child_at(1);
+  EXPECT_FALSE(iframe->IsFencedFrameRoot());
+  EXPECT_FALSE(iframe->IsInFencedFrameTree());
+  const net::IsolationInfo& iframe_isolation_info =
+      iframe->current_frame_host()->GetIsolationInfoForSubresources();
+  EXPECT_FALSE(iframe_isolation_info.nonce().has_value());
+
+  // Navigate the iframe. It should still not have a nonce.
+  EXPECT_TRUE(NavigateToURLFromRenderer(
+      iframe, https_server()->GetURL("b.test", "/title1.html")));
+  const net::IsolationInfo& iframe_new_isolation_info =
+      iframe->current_frame_host()->GetIsolationInfoForSubresources();
+  EXPECT_FALSE(iframe_new_isolation_info.nonce().has_value());
+
+  // Add a nested iframe inside the fenced frame.
+  EXPECT_TRUE(ExecJs(fenced_frame,
+                     "var iframe_within_ff = document.createElement('iframe');"
+                     "document.body.appendChild(iframe_within_ff);"));
+  EXPECT_EQ(1U, fenced_frame->child_count());
+  EXPECT_FALSE(fenced_frame->child_at(0)->IsFencedFrameRoot());
+  EXPECT_TRUE(fenced_frame->child_at(0)->IsInFencedFrameTree());
+  const net::IsolationInfo& nested_iframe_isolation_info =
+      fenced_frame->child_at(0)
+          ->current_frame_host()
+          ->GetIsolationInfoForSubresources();
+  EXPECT_TRUE(nested_iframe_isolation_info.nonce().has_value());
+
+  // Check that a nested iframe in the fenced frame tree has the same nonce
+  // value as its parent.
+  EXPECT_EQ(fenced_frame_nonce.value(),
+            nested_iframe_isolation_info.nonce().value());
+  absl::optional<base::UnguessableToken> nested_iframe_nonce =
+      fenced_frame->child_at(0)->fenced_frame_nonce();
+  EXPECT_EQ(nested_iframe_isolation_info.nonce().value(),
+            nested_iframe_nonce.value());
+
+  // Navigate the iframe. It should still have the same nonce.
+  {
+    GURL https_url(https_server()->GetURL("foo.test", "/title2.html"));
+    std::string navigate_script =
+        JsReplace("iframe_within_ff.src = $1;", https_url.spec());
+    NavigateFrameInsideFencedFrameTreeAndWaitForFinishedLoad(
+        fenced_frame->child_at(0), https_url, navigate_script);
+  }
+  const net::IsolationInfo& nested_iframe_new_isolation_info =
+      fenced_frame->child_at(0)
+          ->current_frame_host()
+          ->GetIsolationInfoForSubresources();
+  EXPECT_EQ(nested_iframe_new_isolation_info.nonce().value(),
+            nested_iframe_nonce.value());
+
+  // Add a nested fenced frame.
+  EXPECT_TRUE(
+      ExecJs(fenced_frame,
+             "var nested_fenced_frame = document.createElement('fencedframe');"
+             "document.body.appendChild(nested_fenced_frame);"));
+  EXPECT_EQ(2U, fenced_frame->child_count());
+  auto* nested_fenced_frame = GetFencedFrameRootNode(fenced_frame->child_at(1));
+  EXPECT_TRUE(nested_fenced_frame->IsFencedFrameRoot());
+  EXPECT_TRUE(nested_fenced_frame->IsInFencedFrameTree());
+  absl::optional<base::UnguessableToken> nested_fframe_nonce =
+      nested_fenced_frame->fenced_frame_nonce();
+  EXPECT_TRUE(nested_fframe_nonce.has_value());
+
+  // Check that a nested fenced frame has a different value than its parent
+  // fenced frame.
+  EXPECT_NE(fenced_frame_nonce.value(), nested_fframe_nonce.value());
+
+  // Check that the nonce does not change when there is a cross-document
+  // navigation.
+  {
+    // Navigate the fenced frame.
+    GURL fenced_frame_url(https_server()->GetURL("b.test", "/title1.html"));
+    std::string navigate_script =
+        JsReplace("f.src = $1;", fenced_frame_url.spec());
+    NavigateFrameInsideFencedFrameTreeAndWaitForFinishedLoad(
+        fenced_frame, fenced_frame_url, navigate_script);
+  }
+
+  absl::optional<base::UnguessableToken> new_fenced_frame_nonce =
+      fenced_frame->fenced_frame_nonce();
+  EXPECT_NE(absl::nullopt, new_fenced_frame_nonce);
+  EXPECT_EQ(new_fenced_frame_nonce.value(), fenced_frame_nonce.value());
+}
+
 INSTANTIATE_TEST_SUITE_P(
     All,
     FencedFrameTreeBrowserTest,
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index bfc4351..e33df0f5 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -869,4 +869,23 @@
   }
 }
 
+void FrameTreeNode::SetFencedFrameNonceIfNeeded() {
+  if (!IsInFencedFrameTree()) {
+    return;
+  }
+
+  if (IsFencedFrameRoot()) {
+    fenced_frame_nonce_ = base::UnguessableToken::Create();
+    return;
+  }
+
+  // For nested iframes in a fenced frame tree, propagate the same nonce as was
+  // set in the fenced frame root.
+  DCHECK(parent_);
+  absl::optional<base::UnguessableToken> nonce =
+      parent_->frame_tree_node()->fenced_frame_nonce();
+  DCHECK(nonce.has_value());
+  fenced_frame_nonce_ = nonce;
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/frame_tree_node.h b/content/browser/renderer_host/frame_tree_node.h
index 4c4d7b9..32382cb2 100644
--- a/content/browser/renderer_host/frame_tree_node.h
+++ b/content/browser/renderer_host/frame_tree_node.h
@@ -487,6 +487,10 @@
   bool HasNavigation();
 
   // Fenced frames (meta-bug crbug.com/1111084):
+  // Note that these two functions cannot be invoked from a FrameTree's or
+  // its root node's constructor since they require the frame tree and the
+  // root node to be completely constructed.
+  //
   // Returns false if fenced frames are disabled. Returns true if the feature is
   // enabled and if |this| is a fenced frame. Returns false for
   // iframes embedded in a fenced frame. To clarify: for the MPArch
@@ -500,6 +504,18 @@
   // fenced frame.
   bool IsInFencedFrameTree() const;
 
+  // Returns a valid nonce if `IsInFencedFrameTree()` returns true for `this`.
+  // Returns nullopt otherwise. See comments on `fenced_frame_nonce_` for more
+  // details.
+  absl::optional<base::UnguessableToken> fenced_frame_nonce() {
+    return fenced_frame_nonce_;
+  }
+
+  // If applicable, set the fenced frame nonce. See comment on
+  // fenced_frame_nonce() for when it is set to a non-null value. Invoked
+  // by FrameTree::Init() or FrameTree::AddFrame().
+  void SetFencedFrameNonceIfNeeded();
+
   // Sets the unique_name and name fields on replication_state_. To be used in
   // prerender activation to make sure the FrameTreeNode replication state is
   // correct after the RenderFrameHost is moved between FrameTreeNodes. The
@@ -682,6 +698,22 @@
   // to the core logic of FrameTreeNode.
   FrameTreeNodeBlameContext blame_context_;
 
+  // Fenced Frames:
+  // Nonce used in the net::IsolationInfo and blink::StorageKey for a fenced
+  // frame and any iframes nested within it. Not set if this frame is not in a
+  // fenced frame's FrameTree. Note that this could be a field in FrameTree for
+  // the MPArch version but for the shadow DOM version we need to keep it here
+  // since the fenced frame root is not a main frame for the latter. The value
+  // of the nonce will be the same for all of the the frames inside a fenced
+  // frame tree. If there is a nested fenced frame it will have a different
+  // nonce than its parent fenced frame. The nonce will stay the same across
+  // navigations because it is always used in conjunction with other fields of
+  // the keys. If the navigation is same-origin/site then the same network stack
+  // partition/storage will be reused and if it's cross-origin/site then other
+  // parts of the key will change and so, even with the same nonce, another
+  // partition will be used.
+  absl::optional<base::UnguessableToken> fenced_frame_nonce_;
+
   // Manages creation and swapping of RenderFrameHosts for this frame.
   //
   // This field needs to be declared last, because destruction of
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 1b377f41..57556f9 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -3713,8 +3713,24 @@
     candidate_site_for_cookies = net::SiteForCookies(top_frame_site);
   }
 
-  const base::UnguessableToken* nonce =
-      anonymous ? &GetPage().anonymous_iframes_nonce() : nullptr;
+  const base::UnguessableToken* nonce = nullptr;
+
+  absl::optional<base::UnguessableToken> fenced_frame_nonce =
+      frame_tree_node_->fenced_frame_nonce();
+
+  // If it's an anonymous frame tree, use its nonce even if it's within a fenced
+  // frame tree to maintain the guarantee that an anonymous frame tree has
+  // a unique nonce. Otherwise, use the fenced frame nonce for fenced frames.
+  // Note that MPArch will ensure that fenced frame tree within an anonymous
+  // iframe does not have `anonymous` set to true. The ShadowDOM architecture
+  // cannot make the same guarantee that MPArch will, and therefore the shadow
+  // DOM version and will lead to the anonymous iframe nonce being used
+  // (crbug.com/1249865).
+  if (anonymous) {
+    nonce = &GetPage().anonymous_iframes_nonce();
+  } else if (fenced_frame_nonce.has_value()) {
+    nonce = &(fenced_frame_nonce.value());
+  }
 
   return net::IsolationInfo::Create(request_type, top_frame_origin,
                                     frame_origin, candidate_site_for_cookies,
@@ -12666,6 +12682,7 @@
   }
   reporting_source = base::UnguessableToken::Create();
 }
+
 RenderFrameHostImpl::DocumentAssociatedData::~DocumentAssociatedData() =
     default;
 
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index f788e63..787502c 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -3479,6 +3479,7 @@
     switches::kForceGpuMemAvailableMb,
     switches::kForceHighContrast,
     switches::kForceOverlayFullscreenVideo,
+    switches::kForceRasterColorProfile,
     switches::kForceVideoOverlays,
     switches::kFullMemoryCrashReport,
     switches::kGaiaUrl,
diff --git a/content/browser/renderer_host/render_widget_host_browsertest.cc b/content/browser/renderer_host/render_widget_host_browsertest.cc
index f9b0a86..616febc 100644
--- a/content/browser/renderer_host/render_widget_host_browsertest.cc
+++ b/content/browser/renderer_host/render_widget_host_browsertest.cc
@@ -723,13 +723,16 @@
           width: env(fold-width, 1px);
           height: env(fold-height, 1px);
         }
-        @media (screen-spanning: none) {
+        @media (horizontal-viewport-segments: 1) and
+               (vertical-viewport-segments: 1) {
           div { opacity: 0.1; }
         }
-        @media (screen-spanning: single-fold-vertical) {
+        @media (horizontal-viewport-segments: 2) and
+               (vertical-viewport-segments: 1) {
           div { opacity: 0.2; }
         }
-        @media (screen-spanning: single-fold-horizontal) {
+        @media (horizontal-viewport-segments: 1) and
+               (vertical-viewport-segments: 2) {
           div { opacity: 0.3; }
         }
       </style>
@@ -852,7 +855,8 @@
   const char kTestPageURL[] =
       R"HTML(data:text/html,<!DOCTYPE html>
       <style>
-        @media (screen-spanning: single-fold-vertical) {
+        @media (horizontal-viewport-segments: 2) and
+               (vertical-viewport-segments: 1) {
           div { margin-left: env(fold-left, 10px); }
         }
       </style>
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 3ec7188..6b8fe3a 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -1879,11 +1879,6 @@
     view_->GetScreenInfo(result);
   else
     display::DisplayUtil::GetDefaultScreenInfo(result);
-
-  if (display::Display::HasForceRasterColorProfile()) {
-    result->display_color_spaces = gfx::DisplayColorSpaces(
-        display::Display::GetForcedRasterColorProfile());
-  }
 }
 
 float RenderWidgetHostImpl::GetDeviceScaleFactor() {
@@ -2145,10 +2140,6 @@
     }
     display::ScreenInfo screen_info;
     display::DisplayUtil::DisplayToScreenInfo(&screen_info, display);
-    if (display::Display::HasForceRasterColorProfile()) {
-      screen_info.display_color_spaces = gfx::DisplayColorSpaces(
-          display::Display::GetForcedRasterColorProfile());
-    }
     result.screen_infos.push_back(screen_info);
   }
 
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index a8e0859..969e09b 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -1871,32 +1871,6 @@
     "../browser/aggregation_service/aggregation_service_key_fetcher_unittest.cc",
     "../browser/aggregation_service/aggregation_service_storage_unittest.cc",
     "../browser/aggregation_service/public_key_parsing_utils_unittest.cc",
-    "../browser/appcache/appcache_cache_test_helper.cc",
-    "../browser/appcache/appcache_cache_test_helper.h",
-    "../browser/appcache/appcache_cache_test_helper_unittest.cc",
-    "../browser/appcache/appcache_database_unittest.cc",
-    "../browser/appcache/appcache_disk_cache_unittest.cc",
-    "../browser/appcache/appcache_group_unittest.cc",
-    "../browser/appcache/appcache_host_unittest.cc",
-    "../browser/appcache/appcache_manifest_parser_unittest.cc",
-    "../browser/appcache/appcache_quota_client_unittest.cc",
-    "../browser/appcache/appcache_request_handler_unittest.cc",
-    "../browser/appcache/appcache_response_unittest.cc",
-    "../browser/appcache/appcache_service_unittest.cc",
-    "../browser/appcache/appcache_storage_impl_unittest.cc",
-    "../browser/appcache/appcache_storage_unittest.cc",
-    "../browser/appcache/appcache_test_helper.cc",
-    "../browser/appcache/appcache_test_helper.h",
-    "../browser/appcache/appcache_unittest.cc",
-    "../browser/appcache/appcache_update_job_unittest.cc",
-    "../browser/appcache/chrome_appcache_service_unittest.cc",
-    "../browser/appcache/mock_appcache_policy.cc",
-    "../browser/appcache/mock_appcache_policy.h",
-    "../browser/appcache/mock_appcache_service.cc",
-    "../browser/appcache/mock_appcache_service.h",
-    "../browser/appcache/mock_appcache_storage.cc",
-    "../browser/appcache/mock_appcache_storage.h",
-    "../browser/appcache/mock_appcache_storage_unittest.cc",
     "../browser/background_fetch/background_fetch_cross_origin_filter_unittest.cc",
     "../browser/background_fetch/background_fetch_data_manager_unittest.cc",
     "../browser/background_fetch/background_fetch_delegate_proxy_unittest.cc",
diff --git a/content/test/data/gpu/pixel_webgl_webcodecs_breakoutbox_displays_frame.html b/content/test/data/gpu/pixel_webgl_webcodecs_breakoutbox_displays_frame.html
index 2bd1385e6..5925f0f 100644
--- a/content/test/data/gpu/pixel_webgl_webcodecs_breakoutbox_displays_frame.html
+++ b/content/test/data/gpu/pixel_webgl_webcodecs_breakoutbox_displays_frame.html
@@ -19,6 +19,12 @@
 <script>
 var gl, generator, writer;
 
+function waitForNextVSync() {
+  return new Promise((resolve, _) => {
+    window.requestAnimationFrame(resolve);
+  });
+}
+
 function runTest() {
   var canvas = new OffscreenCanvas(300, 300);
   gl = initGL(canvas);
@@ -39,7 +45,13 @@
 
   let frame = new VideoFrame(canvas);
   let video = document.querySelector('video');
-  video.requestVideoFrameCallback(_ => {
+  video.requestVideoFrameCallback(async _ => {
+    // Wait for several vsyncs before taking a snapshot, this deflakes the test.
+    // pixel_video_test.js uses addSwapCompletionEventListener() for the same
+    // purpose, but addSwapCompletionEventListener() is not compatible with
+    // Android video overlays, so we can't use those.
+    for (let i = 0; i < 30; i++)
+      await waitForNextVSync();
     domAutomationController.send("SUCCESS");
   });
 
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 3566938..fea0a1d 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -128,32 +128,6 @@
   environment_variables = [ "AFL_DRIVER_DONT_DEFER=1" ]
 }
 
-proto_library("appcache_fuzzer_proto") {
-  sources = [ "../../browser/appcache/appcache_fuzzer.proto" ]
-  testonly = true
-}
-
-fuzzer_test("appcache_fuzzer") {
-  sources = [
-    "../../browser/appcache/appcache_fuzzer.cc",
-    "../../browser/appcache/mock_appcache_storage.cc",
-    "../../browser/appcache/mock_appcache_storage.h",
-  ]
-
-  deps = [
-    ":appcache_fuzzer_proto",
-    "//base/test:test_support",
-    "//content/app:for_content_tests",
-    "//content/browser:browser",
-    "//content/public/browser:browser_sources",
-    "//content/test:test_support",
-    "//mojo/core/embedder",
-    "//services/network:test_support",
-    "//storage/browser:test_support",
-    "//third_party/libprotobuf-mutator",
-  ]
-}
-
 mojolpm_fuzzer_test("code_cache_host_mojolpm_fuzzer") {
   sources = [ "code_cache_host_mojolpm_fuzzer.cc" ]
 
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc
index 90403667..a1b4509 100644
--- a/extensions/browser/extension_function.cc
+++ b/extensions/browser/extension_function.cc
@@ -593,6 +593,9 @@
 }
 
 void ExtensionFunction::Shutdown() {
+  // Allow the extension function to perform any cleanup before nulling out
+  // `browser_context_`.
+  OnBrowserContextShutdown();
   browser_context_ = nullptr;
 }
 
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h
index bafd2d1..ce94103 100644
--- a/extensions/browser/extension_function.h
+++ b/extensions/browser/extension_function.h
@@ -465,6 +465,13 @@
   // additional work or cleanup.
   virtual void OnResponded();
 
+  // Called when the `browser_context_` associated with this ExtensionFunction
+  // is shutting down. Immediately after this call, `browser_context_` will be
+  // set to null. Subclasses should override this method to perform any cleanup
+  // that needs to happen before the context shuts down, such as removing
+  // observers of KeyedServices.
+  virtual void OnBrowserContextShutdown() {}
+
   // Return true if the argument to this function at |index| was provided and
   // is non-null.
   bool HasOptionalArgument(size_t index);
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index 70801f7b..3a5eaaa1 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -256,6 +256,8 @@
         extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
         content::Source<BrowserContext>(browser_context_),
         content::Details<ExtensionHost>(this));
+    ExtensionHostRegistry::Get(browser_context_)
+        ->ExtensionHostCompletedFirstLoad(this);
     for (auto& observer : observer_list_)
       observer.OnExtensionHostDidStopFirstLoad(this);
   }
diff --git a/extensions/browser/extension_host_registry.cc b/extensions/browser/extension_host_registry.cc
index e825882..728e2a7 100644
--- a/extensions/browser/extension_host_registry.cc
+++ b/extensions/browser/extension_host_registry.cc
@@ -93,7 +93,7 @@
     ExtensionHost* extension_host) {
   // NOTE: We don't do
   //
-  // DCHECK(base::Contains(extension_hosts, extension_host);
+  // DCHECK(base::Contains(extension_hosts_, extension_host);
   //
   // because the ExtensionHostCreated() signal is only fired when the
   // renderer process has been initialized, and an ExtensionHost could
@@ -106,6 +106,38 @@
   }
 }
 
+void ExtensionHostRegistry::ExtensionHostCompletedFirstLoad(
+    ExtensionHost* extension_host) {
+  // NOTE: We can't do
+  //
+  // DCHECK(base::Contains(extension_hosts_, extension_host);
+  //
+  // For a combination of convoluted reasons, which should probably change:
+  // 1) ExtensionHostCreated() is triggered when the renderer process has been
+  //    initialized, rather than in its ctor.
+  // 2) When a renderer process is terminated, it causes the RenderFrameHostImpl
+  //    to reset its loading state, which calls DidStopLoading() if it was
+  //    loading. Then, if the first load never happened, ExtensionHost will fire
+  //    the DidCompleteFirstLoad() notification.
+  //
+  // TODO(devlin): Both of these should be fixed. Since code is relying on the
+  // existing semantics of ExtensionHostCreated(), we should probably just
+  // rename it to be more clear (e.g., OnExtensionHostReady() or similar?).
+  // Issue 2) is more subtle, and is probably actually a behavioral bug. We
+  // should probably have ExtensionHost check whether the renderer is still
+  // around or whether the load succeeded before notifying observers, or at
+  // least indicate the success in the notification.
+  //
+  // Because of these issues, we instead insert the extension host here, if we
+  // weren't already tracking it.
+  extension_hosts_.insert(extension_host);
+
+  for (Observer& observer : observers_) {
+    observer.OnExtensionHostCompletedFirstLoad(
+        extension_host->browser_context(), extension_host);
+  }
+}
+
 void ExtensionHostRegistry::AddObserver(Observer* observer) {
   observers_.AddObserver(observer);
 }
diff --git a/extensions/browser/extension_host_registry.h b/extensions/browser/extension_host_registry.h
index 62bd81f5..05c3bbd 100644
--- a/extensions/browser/extension_host_registry.h
+++ b/extensions/browser/extension_host_registry.h
@@ -41,6 +41,16 @@
     virtual void OnExtensionHostDestroyed(
         content::BrowserContext* browser_context,
         ExtensionHost* host) {}
+
+    // Called when an ExtensionHost completes its first load. The
+    // `browser_context` is the context associated with that host (which might
+    // be an incognito version of ExtensionHostRegistry::browser_context_).
+    // Note: If you only need to observe a single ExtensionHost (that's already
+    // created), prefer overriding
+    // ExtensionHostObserver::OnExtensionHostDidStopFirstLoad().
+    virtual void OnExtensionHostCompletedFirstLoad(
+        content::BrowserContext* browser_context,
+        ExtensionHost* host) {}
   };
 
   ExtensionHostRegistry();
@@ -63,6 +73,8 @@
   // Called when an ExtensionHost is destroyed. Stops tracking the host and
   // notifies observers.
   void ExtensionHostDestroyed(ExtensionHost* extension_host);
+  // Called when an ExtensionHost completes its first load.
+  void ExtensionHostCompletedFirstLoad(ExtensionHost* extension_host);
 
   void AddObserver(Observer* observer);
   void RemoveObserver(Observer* observer);
diff --git a/extensions/browser/lazy_background_task_queue.cc b/extensions/browser/lazy_background_task_queue.cc
index 0b46e01a29..02f8f758 100644
--- a/extensions/browser/lazy_background_task_queue.cc
+++ b/extensions/browser/lazy_background_task_queue.cc
@@ -9,7 +9,6 @@
 #include "base/containers/contains.h"
 #include "base/notreached.h"
 #include "content/public/browser/browser_context.h"
-#include "content/public/browser/notification_service.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/site_instance.h"
@@ -18,7 +17,6 @@
 #include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/lazy_background_task_queue_factory.h"
 #include "extensions/browser/lazy_context_id.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/browser/process_map.h"
 #include "extensions/common/extension.h"
@@ -45,10 +43,6 @@
 LazyBackgroundTaskQueue::LazyBackgroundTaskQueue(
     content::BrowserContext* browser_context)
     : browser_context_(browser_context) {
-  registrar_.Add(this,
-                 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
-                 content::NotificationService::AllBrowserContextsAndSources());
-
   extension_registry_observation_.Observe(
       ExtensionRegistry::Get(browser_context));
   extension_host_registry_observation_.Observe(
@@ -166,14 +160,11 @@
   }
 }
 
-void LazyBackgroundTaskQueue::Observe(
-    int type,
-    const content::NotificationSource& source,
-    const content::NotificationDetails& details) {
-  DCHECK_EQ(extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, type);
+void LazyBackgroundTaskQueue::OnExtensionHostCompletedFirstLoad(
+    content::BrowserContext* browser_context,
+    ExtensionHost* host) {
   // If an on-demand background page finished loading, dispatch queued up
   // events for it.
-  ExtensionHost* host = content::Details<ExtensionHost>(details).ptr();
   if (host->extension_host_type() ==
       mojom::ViewType::kExtensionBackgroundPage) {
     CHECK(host->has_loaded_once());
diff --git a/extensions/browser/lazy_background_task_queue.h b/extensions/browser/lazy_background_task_queue.h
index 09e86e5a..016eb24 100644
--- a/extensions/browser/lazy_background_task_queue.h
+++ b/extensions/browser/lazy_background_task_queue.h
@@ -15,8 +15,6 @@
 #include "base/gtest_prod_util.h"
 #include "base/scoped_observation.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
 #include "extensions/browser/extension_host_registry.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_observer.h"
@@ -40,7 +38,6 @@
 // only with extensions that have not-yet-loaded lazy background pages.
 class LazyBackgroundTaskQueue : public KeyedService,
                                 public LazyContextTaskQueue,
-                                public content::NotificationObserver,
                                 public ExtensionRegistryObserver,
                                 public ExtensionHostRegistry::Observer {
  public:
@@ -79,12 +76,10 @@
   using PendingTasksMap =
       std::map<PendingTasksKey, std::unique_ptr<PendingTasksList>>;
 
-  // content::NotificationObserver interface.
-  void Observe(int type,
-               const content::NotificationSource& source,
-               const content::NotificationDetails& details) override;
-
   // ExtensionHostRegistry::Observer:
+  void OnExtensionHostCompletedFirstLoad(
+      content::BrowserContext* browser_context,
+      ExtensionHost* host) override;
   void OnExtensionHostDestroyed(content::BrowserContext* browser_context,
                                 ExtensionHost* host) override;
 
@@ -115,7 +110,6 @@
       const Extension* extension);
 
   content::BrowserContext* browser_context_;
-  content::NotificationRegistrar registrar_;
   PendingTasksMap pending_tasks_;
 
   base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
diff --git a/fuchsia/cipd/BUILD.gn b/fuchsia/cipd/BUILD.gn
index 3fbfbe3..23f23b3d 100644
--- a/fuchsia/cipd/BUILD.gn
+++ b/fuchsia/cipd/BUILD.gn
@@ -267,16 +267,11 @@
 
 build_id_dir(_build_ids_target) {
   testonly = true
-  build_id_dirs = [
-    "${root_gen_dir}/fuchsia/engine/web_engine",
-    "${root_gen_dir}/fuchsia/runners/cast_runner",
-    "${root_gen_dir}/fuchsia/runners/web_runner",
-  ]
-
   output_path = _debug_symbols_outdir
   deps = [
     ":test_packages_for_deps",
     "//fuchsia/engine:web_engine",
+    "//fuchsia/engine:web_engine_shell_pkg",
     "//fuchsia/runners:cast_runner_pkg",
     "//fuchsia/runners:web_runner_pkg",
   ]
diff --git a/gpu/command_buffer/service/shared_image_video_image_reader.cc b/gpu/command_buffer/service/shared_image_video_image_reader.cc
index cac2c5e..4e15af6 100644
--- a/gpu/command_buffer/service/shared_image_video_image_reader.cc
+++ b/gpu/command_buffer/service/shared_image_video_image_reader.cc
@@ -151,9 +151,16 @@
     auto helper_destruction_cb = base::BindPostTask(
         gpu_main_task_runner_,
         base::BindOnce(
-            [](std::unique_ptr<ContextLostObserverHelper> context_lost_helper) {
+            [](std::unique_ptr<ContextLostObserverHelper> context_lost_helper,
+               scoped_refptr<StreamTextureSharedImageInterface>
+                   stream_texture_sii) {
+              // Reset the |stream_texture_sii| first so that its ref in the
+              // |context_lost_helper| gets reset under the DrDc lock.
+              stream_texture_sii.reset();
+              context_lost_helper.reset();
             }));
-    std::move(helper_destruction_cb).Run(std::move(context_lost_helper_));
+    std::move(helper_destruction_cb)
+        .Run(std::move(context_lost_helper_), std::move(stream_texture_sii_));
   }
 }
 
@@ -626,6 +633,7 @@
   {
     base::AutoLockMaybe auto_lock(GetDrDcLockPtr());
     stream_texture_sii_->ReleaseResources();
+    stream_texture_sii_.reset();
   }
 }
 
diff --git a/gpu/command_buffer/service/wrapped_sk_image.cc b/gpu/command_buffer/service/wrapped_sk_image.cc
index 7bf6d7e9..e3b4ced 100644
--- a/gpu/command_buffer/service/wrapped_sk_image.cc
+++ b/gpu/command_buffer/service/wrapped_sk_image.cc
@@ -281,12 +281,14 @@
         break;
       }
 #endif
+#if BUILDFLAG(ENABLE_VULKAN)
       case GrBackendApi::kVulkan: {
         GrVkImageInfo image_info;
         if (backend_texture_.getVkImageInfo(&image_info))
           tracing_id_ = reinterpret_cast<uint64_t>(image_info.fImage);
         break;
       }
+#endif
 #if BUILDFLAG(SKIA_USE_DAWN)
       case GrBackendApi::kDawn: {
         GrDawnTextureInfo tex_info;
diff --git a/headless/lib/browser/headless_clipboard.cc b/headless/lib/browser/headless_clipboard.cc
index c08f934..d8eaa386e 100644
--- a/headless/lib/browser/headless_clipboard.cc
+++ b/headless/lib/browser/headless_clipboard.cc
@@ -79,26 +79,6 @@
 
 // |data_dst| is not used. It's only passed to be consistent with other
 // platforms.
-std::vector<std::u16string>
-HeadlessClipboard::ReadAvailablePlatformSpecificFormatNames(
-    ui::ClipboardBuffer buffer,
-    const ui::DataTransferEndpoint* data_dst) const {
-  const auto& data = GetStore(buffer).data;
-  std::vector<std::u16string> types;
-  types.reserve(data.size());
-  std::map<std::string, std::string> custom_format_names =
-      ExtractCustomPlatformNames(buffer, data_dst);
-  for (const auto& item : custom_format_names)
-    types.push_back(base::UTF8ToUTF16(item.first));
-  for (const auto& item : GetStandardFormats(buffer, data_dst)) {
-    types.push_back(item);
-  }
-
-  return types;
-}
-
-// |data_dst| is not used. It's only passed to be consistent with other
-// platforms.
 void HeadlessClipboard::ReadText(ui::ClipboardBuffer buffer,
                                  const ui::DataTransferEndpoint* data_dst,
                                  std::u16string* result) const {
diff --git a/headless/lib/browser/headless_clipboard.h b/headless/lib/browser/headless_clipboard.h
index 06dae11d..534a371d 100644
--- a/headless/lib/browser/headless_clipboard.h
+++ b/headless/lib/browser/headless_clipboard.h
@@ -32,6 +32,9 @@
       ui::ClipboardBuffer buffer) const override;
   const ui::ClipboardSequenceNumberToken& GetSequenceNumber(
       ui::ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ui::ClipboardBuffer buffer,
+      const ui::DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(
       const ui::ClipboardFormatType& format,
       ui::ClipboardBuffer buffer,
@@ -40,9 +43,6 @@
   void ReadAvailableTypes(ui::ClipboardBuffer buffer,
                           const ui::DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ui::ClipboardBuffer buffer,
-      const ui::DataTransferEndpoint* data_dst) const override;
   void ReadText(ui::ClipboardBuffer buffer,
                 const ui::DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -125,16 +125,6 @@
   DataStore& GetStore(ui::ClipboardBuffer buffer);
   DataStore& GetDefaultStore();
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  // TODO(snianu): Create a more generalized function for standard formats that
-  // can be shared by all platforms.
-  std::vector<std::u16string> GetStandardFormats(
-      ui::ClipboardBuffer buffer,
-      const ui::DataTransferEndpoint* data_dst) const;
-
   ui::ClipboardBuffer default_store_buffer_;
   mutable std::map<ui::ClipboardBuffer, DataStore> stores_;
 };
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
index adc8358..daf1ca6 100644
--- a/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
+++ b/ios/chrome/test/earl_grey/chrome_earl_grey_app_interface.mm
@@ -661,10 +661,15 @@
 }
 
 + (NSError*)purgeCachedWebViewPages {
-  if (!chrome_test_util::ClearAllBrowsingData(false)) {
+  web::WebState* web_state = chrome_test_util::GetCurrentWebState();
+  web_state->SetWebUsageEnabled(false);
+  if (!chrome_test_util::RemoveBrowsingCache()) {
     return testing::NSErrorWithLocalizedDescription(
         @"Fail to purge cached web view pages.");
   }
+  web_state->SetWebUsageEnabled(true);
+  web_state->GetNavigationManager()->LoadIfNecessary();
+
   return nil;
 }
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 45ec879a..1ce4cebf 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -5121,7 +5121,7 @@
     ":net_fuzzer_test_support",
     "//net",
   ]
-  seed_corpus = "data/fuzzer_data/net_canonical_cookie_fuzzer/"
+  seed_corpus = "data/fuzzer_data/cookies/"
 }
 
 fuzzer_test("net_cookie_partition_key_fuzzer") {
@@ -5138,6 +5138,7 @@
     ":net_fuzzer_test_support",
     "//net",
   ]
+  seed_corpus = "data/fuzzer_data/cookies/"
 }
 
 fuzzer_test("net_http_stream_parser_fuzzer") {
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/01148e9defeae5891c99f04544ea331a0e5289ec b/net/data/fuzzer_data/cookies/01148e9defeae5891c99f04544ea331a0e5289ec
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/01148e9defeae5891c99f04544ea331a0e5289ec
rename to net/data/fuzzer_data/cookies/01148e9defeae5891c99f04544ea331a0e5289ec
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/01dee8260b70f2e55c4f4fbf40c073a800adfa6e b/net/data/fuzzer_data/cookies/01dee8260b70f2e55c4f4fbf40c073a800adfa6e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/01dee8260b70f2e55c4f4fbf40c073a800adfa6e
rename to net/data/fuzzer_data/cookies/01dee8260b70f2e55c4f4fbf40c073a800adfa6e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0284b34ab88997023d70112f8a094b56ef8bfef0 b/net/data/fuzzer_data/cookies/0284b34ab88997023d70112f8a094b56ef8bfef0
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0284b34ab88997023d70112f8a094b56ef8bfef0
rename to net/data/fuzzer_data/cookies/0284b34ab88997023d70112f8a094b56ef8bfef0
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/03429a858215bba11994af0abdf0912d9c14ee0c b/net/data/fuzzer_data/cookies/03429a858215bba11994af0abdf0912d9c14ee0c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/03429a858215bba11994af0abdf0912d9c14ee0c
rename to net/data/fuzzer_data/cookies/03429a858215bba11994af0abdf0912d9c14ee0c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/03a79f27987511c315b984d435dfc15ae78254a3 b/net/data/fuzzer_data/cookies/03a79f27987511c315b984d435dfc15ae78254a3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/03a79f27987511c315b984d435dfc15ae78254a3
rename to net/data/fuzzer_data/cookies/03a79f27987511c315b984d435dfc15ae78254a3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/04d51c85a2491ce50c566002a3bdfaf3106a6b47 b/net/data/fuzzer_data/cookies/04d51c85a2491ce50c566002a3bdfaf3106a6b47
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/04d51c85a2491ce50c566002a3bdfaf3106a6b47
rename to net/data/fuzzer_data/cookies/04d51c85a2491ce50c566002a3bdfaf3106a6b47
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0506230a41aca38bb0ffb5de3f55058d41a498af b/net/data/fuzzer_data/cookies/0506230a41aca38bb0ffb5de3f55058d41a498af
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0506230a41aca38bb0ffb5de3f55058d41a498af
rename to net/data/fuzzer_data/cookies/0506230a41aca38bb0ffb5de3f55058d41a498af
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/05b4801f8b8dfbd1769c4fa871bb183b61456c4e b/net/data/fuzzer_data/cookies/05b4801f8b8dfbd1769c4fa871bb183b61456c4e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/05b4801f8b8dfbd1769c4fa871bb183b61456c4e
rename to net/data/fuzzer_data/cookies/05b4801f8b8dfbd1769c4fa871bb183b61456c4e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/05e36c1756f2385dfd7f9b62e906163b0fd11de1 b/net/data/fuzzer_data/cookies/05e36c1756f2385dfd7f9b62e906163b0fd11de1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/05e36c1756f2385dfd7f9b62e906163b0fd11de1
rename to net/data/fuzzer_data/cookies/05e36c1756f2385dfd7f9b62e906163b0fd11de1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/06a27e351cddd2a49703ba85bd8f007c9aa44086 b/net/data/fuzzer_data/cookies/06a27e351cddd2a49703ba85bd8f007c9aa44086
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/06a27e351cddd2a49703ba85bd8f007c9aa44086
rename to net/data/fuzzer_data/cookies/06a27e351cddd2a49703ba85bd8f007c9aa44086
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/06f1e5d8c336b82473abed2c49fb41ad6834e079 b/net/data/fuzzer_data/cookies/06f1e5d8c336b82473abed2c49fb41ad6834e079
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/06f1e5d8c336b82473abed2c49fb41ad6834e079
rename to net/data/fuzzer_data/cookies/06f1e5d8c336b82473abed2c49fb41ad6834e079
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/07c9c06643ad6cb58fdedca83573f7ebd0406e3e b/net/data/fuzzer_data/cookies/07c9c06643ad6cb58fdedca83573f7ebd0406e3e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/07c9c06643ad6cb58fdedca83573f7ebd0406e3e
rename to net/data/fuzzer_data/cookies/07c9c06643ad6cb58fdedca83573f7ebd0406e3e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/087b52f241d0f932dc3abcf6a343514f7fc24854 b/net/data/fuzzer_data/cookies/087b52f241d0f932dc3abcf6a343514f7fc24854
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/087b52f241d0f932dc3abcf6a343514f7fc24854
rename to net/data/fuzzer_data/cookies/087b52f241d0f932dc3abcf6a343514f7fc24854
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/08aa1ae92143a6d4e4aa3df3157497d250b0d04b b/net/data/fuzzer_data/cookies/08aa1ae92143a6d4e4aa3df3157497d250b0d04b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/08aa1ae92143a6d4e4aa3df3157497d250b0d04b
rename to net/data/fuzzer_data/cookies/08aa1ae92143a6d4e4aa3df3157497d250b0d04b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/09ecf26720791d33b4f4f53d50b1c89b6393e2d6 b/net/data/fuzzer_data/cookies/09ecf26720791d33b4f4f53d50b1c89b6393e2d6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/09ecf26720791d33b4f4f53d50b1c89b6393e2d6
rename to net/data/fuzzer_data/cookies/09ecf26720791d33b4f4f53d50b1c89b6393e2d6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0a911b70d892516fe5baa26d9fcb74df857491c4 b/net/data/fuzzer_data/cookies/0a911b70d892516fe5baa26d9fcb74df857491c4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0a911b70d892516fe5baa26d9fcb74df857491c4
rename to net/data/fuzzer_data/cookies/0a911b70d892516fe5baa26d9fcb74df857491c4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0ab0209635f1475211b92f8a0918902a8020e173 b/net/data/fuzzer_data/cookies/0ab0209635f1475211b92f8a0918902a8020e173
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0ab0209635f1475211b92f8a0918902a8020e173
rename to net/data/fuzzer_data/cookies/0ab0209635f1475211b92f8a0918902a8020e173
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0b7074781b589cb299157f79bb9eaa377f06fcac b/net/data/fuzzer_data/cookies/0b7074781b589cb299157f79bb9eaa377f06fcac
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0b7074781b589cb299157f79bb9eaa377f06fcac
rename to net/data/fuzzer_data/cookies/0b7074781b589cb299157f79bb9eaa377f06fcac
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0cca316d9c5dfe90bb72147e1e19061ed3d74d48 b/net/data/fuzzer_data/cookies/0cca316d9c5dfe90bb72147e1e19061ed3d74d48
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0cca316d9c5dfe90bb72147e1e19061ed3d74d48
rename to net/data/fuzzer_data/cookies/0cca316d9c5dfe90bb72147e1e19061ed3d74d48
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0d100cbf03c876c74fc13e15e9704fd77422aee9 b/net/data/fuzzer_data/cookies/0d100cbf03c876c74fc13e15e9704fd77422aee9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0d100cbf03c876c74fc13e15e9704fd77422aee9
rename to net/data/fuzzer_data/cookies/0d100cbf03c876c74fc13e15e9704fd77422aee9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0d4451b8d57c4c24c91e0c758837b89e2bf01f43 b/net/data/fuzzer_data/cookies/0d4451b8d57c4c24c91e0c758837b89e2bf01f43
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0d4451b8d57c4c24c91e0c758837b89e2bf01f43
rename to net/data/fuzzer_data/cookies/0d4451b8d57c4c24c91e0c758837b89e2bf01f43
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0e74d4a5af628f624f6ca2847f727a7bed9b46a2 b/net/data/fuzzer_data/cookies/0e74d4a5af628f624f6ca2847f727a7bed9b46a2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0e74d4a5af628f624f6ca2847f727a7bed9b46a2
rename to net/data/fuzzer_data/cookies/0e74d4a5af628f624f6ca2847f727a7bed9b46a2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0e7aa5c3fb119a3da31670208e374ee4caab4710 b/net/data/fuzzer_data/cookies/0e7aa5c3fb119a3da31670208e374ee4caab4710
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0e7aa5c3fb119a3da31670208e374ee4caab4710
rename to net/data/fuzzer_data/cookies/0e7aa5c3fb119a3da31670208e374ee4caab4710
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0eb6de4cdbcf481c51ca734011bac450a2035f9b b/net/data/fuzzer_data/cookies/0eb6de4cdbcf481c51ca734011bac450a2035f9b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0eb6de4cdbcf481c51ca734011bac450a2035f9b
rename to net/data/fuzzer_data/cookies/0eb6de4cdbcf481c51ca734011bac450a2035f9b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/0f04f1a8a1ede89a3105435ae3eefe8ca9a5229f b/net/data/fuzzer_data/cookies/0f04f1a8a1ede89a3105435ae3eefe8ca9a5229f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/0f04f1a8a1ede89a3105435ae3eefe8ca9a5229f
rename to net/data/fuzzer_data/cookies/0f04f1a8a1ede89a3105435ae3eefe8ca9a5229f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/108c5233426c644c01cf2a03fd9e899e8091ba32 b/net/data/fuzzer_data/cookies/108c5233426c644c01cf2a03fd9e899e8091ba32
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/108c5233426c644c01cf2a03fd9e899e8091ba32
rename to net/data/fuzzer_data/cookies/108c5233426c644c01cf2a03fd9e899e8091ba32
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/11f6c5d0b45e0630b719301d7daa3c3e5ade0f2d b/net/data/fuzzer_data/cookies/11f6c5d0b45e0630b719301d7daa3c3e5ade0f2d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/11f6c5d0b45e0630b719301d7daa3c3e5ade0f2d
rename to net/data/fuzzer_data/cookies/11f6c5d0b45e0630b719301d7daa3c3e5ade0f2d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/12e2ed512bf4fce6788a3029bf345132e314e03d b/net/data/fuzzer_data/cookies/12e2ed512bf4fce6788a3029bf345132e314e03d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/12e2ed512bf4fce6788a3029bf345132e314e03d
rename to net/data/fuzzer_data/cookies/12e2ed512bf4fce6788a3029bf345132e314e03d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/1301c1b5fd4c6699783779dc6dff1f55fe216f91 b/net/data/fuzzer_data/cookies/1301c1b5fd4c6699783779dc6dff1f55fe216f91
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/1301c1b5fd4c6699783779dc6dff1f55fe216f91
rename to net/data/fuzzer_data/cookies/1301c1b5fd4c6699783779dc6dff1f55fe216f91
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/143933e4dbf3a1009a19ea3a6cb448232c2254b9 b/net/data/fuzzer_data/cookies/143933e4dbf3a1009a19ea3a6cb448232c2254b9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/143933e4dbf3a1009a19ea3a6cb448232c2254b9
rename to net/data/fuzzer_data/cookies/143933e4dbf3a1009a19ea3a6cb448232c2254b9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/1520d489150e0d97a8cc44becf4bb69897a08605 b/net/data/fuzzer_data/cookies/1520d489150e0d97a8cc44becf4bb69897a08605
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/1520d489150e0d97a8cc44becf4bb69897a08605
rename to net/data/fuzzer_data/cookies/1520d489150e0d97a8cc44becf4bb69897a08605
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/15ddba174a983013fce407cc4bb1f3e0ee428ae3 b/net/data/fuzzer_data/cookies/15ddba174a983013fce407cc4bb1f3e0ee428ae3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/15ddba174a983013fce407cc4bb1f3e0ee428ae3
rename to net/data/fuzzer_data/cookies/15ddba174a983013fce407cc4bb1f3e0ee428ae3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/172558c88170d65ef44569ee9372d53ed25628c9 b/net/data/fuzzer_data/cookies/172558c88170d65ef44569ee9372d53ed25628c9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/172558c88170d65ef44569ee9372d53ed25628c9
rename to net/data/fuzzer_data/cookies/172558c88170d65ef44569ee9372d53ed25628c9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/1993bb226fc2e675a68802ebcef4f79604ea53a2 b/net/data/fuzzer_data/cookies/1993bb226fc2e675a68802ebcef4f79604ea53a2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/1993bb226fc2e675a68802ebcef4f79604ea53a2
rename to net/data/fuzzer_data/cookies/1993bb226fc2e675a68802ebcef4f79604ea53a2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/19aedc04372b6f042832c3b7d61ed5044fa74b7b b/net/data/fuzzer_data/cookies/19aedc04372b6f042832c3b7d61ed5044fa74b7b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/19aedc04372b6f042832c3b7d61ed5044fa74b7b
rename to net/data/fuzzer_data/cookies/19aedc04372b6f042832c3b7d61ed5044fa74b7b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/1afd397fc7d7c6e7d68ef6d1a96599083a014f43 b/net/data/fuzzer_data/cookies/1afd397fc7d7c6e7d68ef6d1a96599083a014f43
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/1afd397fc7d7c6e7d68ef6d1a96599083a014f43
rename to net/data/fuzzer_data/cookies/1afd397fc7d7c6e7d68ef6d1a96599083a014f43
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/1f87d4962ece5125f8f37cb79e0ec9c56db07bff b/net/data/fuzzer_data/cookies/1f87d4962ece5125f8f37cb79e0ec9c56db07bff
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/1f87d4962ece5125f8f37cb79e0ec9c56db07bff
rename to net/data/fuzzer_data/cookies/1f87d4962ece5125f8f37cb79e0ec9c56db07bff
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/21d80e7e6d99989d333cf6ef09612a63bd475cbd b/net/data/fuzzer_data/cookies/21d80e7e6d99989d333cf6ef09612a63bd475cbd
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/21d80e7e6d99989d333cf6ef09612a63bd475cbd
rename to net/data/fuzzer_data/cookies/21d80e7e6d99989d333cf6ef09612a63bd475cbd
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/22196204b3de049525621cfa872aa869554f7c98 b/net/data/fuzzer_data/cookies/22196204b3de049525621cfa872aa869554f7c98
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/22196204b3de049525621cfa872aa869554f7c98
rename to net/data/fuzzer_data/cookies/22196204b3de049525621cfa872aa869554f7c98
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/225906da4bbfe1957593e2f5cc15dfa2dcb47e95 b/net/data/fuzzer_data/cookies/225906da4bbfe1957593e2f5cc15dfa2dcb47e95
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/225906da4bbfe1957593e2f5cc15dfa2dcb47e95
rename to net/data/fuzzer_data/cookies/225906da4bbfe1957593e2f5cc15dfa2dcb47e95
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/22731b8b044b9fbc0097e043cc81911dbbeba916 b/net/data/fuzzer_data/cookies/22731b8b044b9fbc0097e043cc81911dbbeba916
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/22731b8b044b9fbc0097e043cc81911dbbeba916
rename to net/data/fuzzer_data/cookies/22731b8b044b9fbc0097e043cc81911dbbeba916
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/24474bec6890334ccb6eb7b49d915c22ceb6846e b/net/data/fuzzer_data/cookies/24474bec6890334ccb6eb7b49d915c22ceb6846e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/24474bec6890334ccb6eb7b49d915c22ceb6846e
rename to net/data/fuzzer_data/cookies/24474bec6890334ccb6eb7b49d915c22ceb6846e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/25345cb4bfaddc21cfb8f3dd3b39c9a2284c8fb5 b/net/data/fuzzer_data/cookies/25345cb4bfaddc21cfb8f3dd3b39c9a2284c8fb5
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/25345cb4bfaddc21cfb8f3dd3b39c9a2284c8fb5
rename to net/data/fuzzer_data/cookies/25345cb4bfaddc21cfb8f3dd3b39c9a2284c8fb5
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/28012f4d7aaca4f5d608d2facbfd5ad2929932ae b/net/data/fuzzer_data/cookies/28012f4d7aaca4f5d608d2facbfd5ad2929932ae
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/28012f4d7aaca4f5d608d2facbfd5ad2929932ae
rename to net/data/fuzzer_data/cookies/28012f4d7aaca4f5d608d2facbfd5ad2929932ae
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/292ac1731b2b54f4907f5f3bee6be5d12b81421d b/net/data/fuzzer_data/cookies/292ac1731b2b54f4907f5f3bee6be5d12b81421d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/292ac1731b2b54f4907f5f3bee6be5d12b81421d
rename to net/data/fuzzer_data/cookies/292ac1731b2b54f4907f5f3bee6be5d12b81421d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/2c29369ca4e15acef98ca5714ecaf51ab6cc0b95 b/net/data/fuzzer_data/cookies/2c29369ca4e15acef98ca5714ecaf51ab6cc0b95
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/2c29369ca4e15acef98ca5714ecaf51ab6cc0b95
rename to net/data/fuzzer_data/cookies/2c29369ca4e15acef98ca5714ecaf51ab6cc0b95
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/30f38084cb9a3b9cf85c5a26d1eb9e4db03c12ae b/net/data/fuzzer_data/cookies/30f38084cb9a3b9cf85c5a26d1eb9e4db03c12ae
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/30f38084cb9a3b9cf85c5a26d1eb9e4db03c12ae
rename to net/data/fuzzer_data/cookies/30f38084cb9a3b9cf85c5a26d1eb9e4db03c12ae
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/31b176e486ea95bcc24ad077e7e66c9c289a8747 b/net/data/fuzzer_data/cookies/31b176e486ea95bcc24ad077e7e66c9c289a8747
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/31b176e486ea95bcc24ad077e7e66c9c289a8747
rename to net/data/fuzzer_data/cookies/31b176e486ea95bcc24ad077e7e66c9c289a8747
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/331b1d65a67050945e7abcf6b859063b5f5dbe9f b/net/data/fuzzer_data/cookies/331b1d65a67050945e7abcf6b859063b5f5dbe9f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/331b1d65a67050945e7abcf6b859063b5f5dbe9f
rename to net/data/fuzzer_data/cookies/331b1d65a67050945e7abcf6b859063b5f5dbe9f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/34b8439cdcab61b693b00a6981189db9c83fd581 b/net/data/fuzzer_data/cookies/34b8439cdcab61b693b00a6981189db9c83fd581
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/34b8439cdcab61b693b00a6981189db9c83fd581
rename to net/data/fuzzer_data/cookies/34b8439cdcab61b693b00a6981189db9c83fd581
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3639f5b822ca5628cf56f423d980680109b1ae1a b/net/data/fuzzer_data/cookies/3639f5b822ca5628cf56f423d980680109b1ae1a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3639f5b822ca5628cf56f423d980680109b1ae1a
rename to net/data/fuzzer_data/cookies/3639f5b822ca5628cf56f423d980680109b1ae1a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/37229e3a20bf1feb2cedb868c9a0039733f595b9 b/net/data/fuzzer_data/cookies/37229e3a20bf1feb2cedb868c9a0039733f595b9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/37229e3a20bf1feb2cedb868c9a0039733f595b9
rename to net/data/fuzzer_data/cookies/37229e3a20bf1feb2cedb868c9a0039733f595b9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3862571ca3ead4beb0c987fa237f010b89a2d7e1 b/net/data/fuzzer_data/cookies/3862571ca3ead4beb0c987fa237f010b89a2d7e1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3862571ca3ead4beb0c987fa237f010b89a2d7e1
rename to net/data/fuzzer_data/cookies/3862571ca3ead4beb0c987fa237f010b89a2d7e1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3974ec234f5e0fcad2da5b443841741d0d004d8e b/net/data/fuzzer_data/cookies/3974ec234f5e0fcad2da5b443841741d0d004d8e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3974ec234f5e0fcad2da5b443841741d0d004d8e
rename to net/data/fuzzer_data/cookies/3974ec234f5e0fcad2da5b443841741d0d004d8e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3a7d56be05b607dc8855938f3facbd98b279af5e b/net/data/fuzzer_data/cookies/3a7d56be05b607dc8855938f3facbd98b279af5e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3a7d56be05b607dc8855938f3facbd98b279af5e
rename to net/data/fuzzer_data/cookies/3a7d56be05b607dc8855938f3facbd98b279af5e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3bb70a085018d271eb16afee05de6d0645eb0d19 b/net/data/fuzzer_data/cookies/3bb70a085018d271eb16afee05de6d0645eb0d19
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3bb70a085018d271eb16afee05de6d0645eb0d19
rename to net/data/fuzzer_data/cookies/3bb70a085018d271eb16afee05de6d0645eb0d19
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3c89f813069bc9cba07d02cc38282321951eefd2 b/net/data/fuzzer_data/cookies/3c89f813069bc9cba07d02cc38282321951eefd2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3c89f813069bc9cba07d02cc38282321951eefd2
rename to net/data/fuzzer_data/cookies/3c89f813069bc9cba07d02cc38282321951eefd2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/3f6834d53c555de6db8dc9ff78d477726247ebbe b/net/data/fuzzer_data/cookies/3f6834d53c555de6db8dc9ff78d477726247ebbe
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/3f6834d53c555de6db8dc9ff78d477726247ebbe
rename to net/data/fuzzer_data/cookies/3f6834d53c555de6db8dc9ff78d477726247ebbe
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/40810cdd634c8d8fb54a523e9ad0c0bc88cc1147 b/net/data/fuzzer_data/cookies/40810cdd634c8d8fb54a523e9ad0c0bc88cc1147
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/40810cdd634c8d8fb54a523e9ad0c0bc88cc1147
rename to net/data/fuzzer_data/cookies/40810cdd634c8d8fb54a523e9ad0c0bc88cc1147
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/41845281adcde5e78493c709962179a066cd73d3 b/net/data/fuzzer_data/cookies/41845281adcde5e78493c709962179a066cd73d3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/41845281adcde5e78493c709962179a066cd73d3
rename to net/data/fuzzer_data/cookies/41845281adcde5e78493c709962179a066cd73d3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/42f3bd0fb1ece69f762f018eb58bebb9f2ac5836 b/net/data/fuzzer_data/cookies/42f3bd0fb1ece69f762f018eb58bebb9f2ac5836
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/42f3bd0fb1ece69f762f018eb58bebb9f2ac5836
rename to net/data/fuzzer_data/cookies/42f3bd0fb1ece69f762f018eb58bebb9f2ac5836
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/46582500b95a2b1592fc2d12470e69dfac2d29f4 b/net/data/fuzzer_data/cookies/46582500b95a2b1592fc2d12470e69dfac2d29f4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/46582500b95a2b1592fc2d12470e69dfac2d29f4
rename to net/data/fuzzer_data/cookies/46582500b95a2b1592fc2d12470e69dfac2d29f4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4788a8f6103e590553694d34981c5bce2c5261a3 b/net/data/fuzzer_data/cookies/4788a8f6103e590553694d34981c5bce2c5261a3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4788a8f6103e590553694d34981c5bce2c5261a3
rename to net/data/fuzzer_data/cookies/4788a8f6103e590553694d34981c5bce2c5261a3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/47f8e3ebadbf34b9561c03a56c4f45746602c64a b/net/data/fuzzer_data/cookies/47f8e3ebadbf34b9561c03a56c4f45746602c64a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/47f8e3ebadbf34b9561c03a56c4f45746602c64a
rename to net/data/fuzzer_data/cookies/47f8e3ebadbf34b9561c03a56c4f45746602c64a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/483505ae5f32600c62a0ea81f27854303ff9ef59 b/net/data/fuzzer_data/cookies/483505ae5f32600c62a0ea81f27854303ff9ef59
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/483505ae5f32600c62a0ea81f27854303ff9ef59
rename to net/data/fuzzer_data/cookies/483505ae5f32600c62a0ea81f27854303ff9ef59
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/49e4dcb225a3ee35420bfb250fed17651fc132fb b/net/data/fuzzer_data/cookies/49e4dcb225a3ee35420bfb250fed17651fc132fb
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/49e4dcb225a3ee35420bfb250fed17651fc132fb
rename to net/data/fuzzer_data/cookies/49e4dcb225a3ee35420bfb250fed17651fc132fb
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4a3a0a03705536f91f423c540a7c9cd0ff192575 b/net/data/fuzzer_data/cookies/4a3a0a03705536f91f423c540a7c9cd0ff192575
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4a3a0a03705536f91f423c540a7c9cd0ff192575
rename to net/data/fuzzer_data/cookies/4a3a0a03705536f91f423c540a7c9cd0ff192575
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4a6ee003c0a2081d0ea0a3dd5121fb807992749a b/net/data/fuzzer_data/cookies/4a6ee003c0a2081d0ea0a3dd5121fb807992749a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4a6ee003c0a2081d0ea0a3dd5121fb807992749a
rename to net/data/fuzzer_data/cookies/4a6ee003c0a2081d0ea0a3dd5121fb807992749a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4b3fb438a10e86dbf70b15ab144eb3fde2472220 b/net/data/fuzzer_data/cookies/4b3fb438a10e86dbf70b15ab144eb3fde2472220
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4b3fb438a10e86dbf70b15ab144eb3fde2472220
rename to net/data/fuzzer_data/cookies/4b3fb438a10e86dbf70b15ab144eb3fde2472220
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4c42ad64c160d61e899f9d28ef0285372de06e5b b/net/data/fuzzer_data/cookies/4c42ad64c160d61e899f9d28ef0285372de06e5b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4c42ad64c160d61e899f9d28ef0285372de06e5b
rename to net/data/fuzzer_data/cookies/4c42ad64c160d61e899f9d28ef0285372de06e5b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4dbe8da9ff0c924b39cfa4bf79d980577348068a b/net/data/fuzzer_data/cookies/4dbe8da9ff0c924b39cfa4bf79d980577348068a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4dbe8da9ff0c924b39cfa4bf79d980577348068a
rename to net/data/fuzzer_data/cookies/4dbe8da9ff0c924b39cfa4bf79d980577348068a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4e5b007d86df496f7230527124d47f9ec15e86a8 b/net/data/fuzzer_data/cookies/4e5b007d86df496f7230527124d47f9ec15e86a8
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4e5b007d86df496f7230527124d47f9ec15e86a8
rename to net/data/fuzzer_data/cookies/4e5b007d86df496f7230527124d47f9ec15e86a8
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4f5029d0bed2d665cc3453e98d33557b77e57702 b/net/data/fuzzer_data/cookies/4f5029d0bed2d665cc3453e98d33557b77e57702
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4f5029d0bed2d665cc3453e98d33557b77e57702
rename to net/data/fuzzer_data/cookies/4f5029d0bed2d665cc3453e98d33557b77e57702
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fa0f1bcefdfb9beee62de4ca07e4a8bf7fa35e1 b/net/data/fuzzer_data/cookies/4fa0f1bcefdfb9beee62de4ca07e4a8bf7fa35e1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fa0f1bcefdfb9beee62de4ca07e4a8bf7fa35e1
rename to net/data/fuzzer_data/cookies/4fa0f1bcefdfb9beee62de4ca07e4a8bf7fa35e1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fad3a1bd6bcbfc62360d8a1a09c87848e1f3bed b/net/data/fuzzer_data/cookies/4fad3a1bd6bcbfc62360d8a1a09c87848e1f3bed
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fad3a1bd6bcbfc62360d8a1a09c87848e1f3bed
rename to net/data/fuzzer_data/cookies/4fad3a1bd6bcbfc62360d8a1a09c87848e1f3bed
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fd1f6196c115fae6744d3916ce634056ce166a9 b/net/data/fuzzer_data/cookies/4fd1f6196c115fae6744d3916ce634056ce166a9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/4fd1f6196c115fae6744d3916ce634056ce166a9
rename to net/data/fuzzer_data/cookies/4fd1f6196c115fae6744d3916ce634056ce166a9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/503ef1e70ca276089d258d8e009d0466c17db3b3 b/net/data/fuzzer_data/cookies/503ef1e70ca276089d258d8e009d0466c17db3b3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/503ef1e70ca276089d258d8e009d0466c17db3b3
rename to net/data/fuzzer_data/cookies/503ef1e70ca276089d258d8e009d0466c17db3b3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/50c20aec7ff464a1764692b56369f0e10623a5d8 b/net/data/fuzzer_data/cookies/50c20aec7ff464a1764692b56369f0e10623a5d8
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/50c20aec7ff464a1764692b56369f0e10623a5d8
rename to net/data/fuzzer_data/cookies/50c20aec7ff464a1764692b56369f0e10623a5d8
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5100775ff55709c7a73253160210c911903b5fbe b/net/data/fuzzer_data/cookies/5100775ff55709c7a73253160210c911903b5fbe
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5100775ff55709c7a73253160210c911903b5fbe
rename to net/data/fuzzer_data/cookies/5100775ff55709c7a73253160210c911903b5fbe
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/51962c160bd17c5ce0132537f1b3d96f4a3625da b/net/data/fuzzer_data/cookies/51962c160bd17c5ce0132537f1b3d96f4a3625da
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/51962c160bd17c5ce0132537f1b3d96f4a3625da
rename to net/data/fuzzer_data/cookies/51962c160bd17c5ce0132537f1b3d96f4a3625da
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/53b88bd8b0f4d9912e466e583a2085ff984e6240 b/net/data/fuzzer_data/cookies/53b88bd8b0f4d9912e466e583a2085ff984e6240
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/53b88bd8b0f4d9912e466e583a2085ff984e6240
rename to net/data/fuzzer_data/cookies/53b88bd8b0f4d9912e466e583a2085ff984e6240
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/552b9175113106037c5ebb2f3415039bb16ac2d7 b/net/data/fuzzer_data/cookies/552b9175113106037c5ebb2f3415039bb16ac2d7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/552b9175113106037c5ebb2f3415039bb16ac2d7
rename to net/data/fuzzer_data/cookies/552b9175113106037c5ebb2f3415039bb16ac2d7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/562c88df1ab3e5861b2077bdb236b64307a8af49 b/net/data/fuzzer_data/cookies/562c88df1ab3e5861b2077bdb236b64307a8af49
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/562c88df1ab3e5861b2077bdb236b64307a8af49
rename to net/data/fuzzer_data/cookies/562c88df1ab3e5861b2077bdb236b64307a8af49
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5b3d5fb36667f1c3371004c91e4d068fd9466373 b/net/data/fuzzer_data/cookies/5b3d5fb36667f1c3371004c91e4d068fd9466373
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5b3d5fb36667f1c3371004c91e4d068fd9466373
rename to net/data/fuzzer_data/cookies/5b3d5fb36667f1c3371004c91e4d068fd9466373
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5c8ea5d0acd626f4486ca1df63b57f2c01ea58f6 b/net/data/fuzzer_data/cookies/5c8ea5d0acd626f4486ca1df63b57f2c01ea58f6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5c8ea5d0acd626f4486ca1df63b57f2c01ea58f6
rename to net/data/fuzzer_data/cookies/5c8ea5d0acd626f4486ca1df63b57f2c01ea58f6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5e816c1477a71b0927b098bae801c194d8450d42 b/net/data/fuzzer_data/cookies/5e816c1477a71b0927b098bae801c194d8450d42
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5e816c1477a71b0927b098bae801c194d8450d42
rename to net/data/fuzzer_data/cookies/5e816c1477a71b0927b098bae801c194d8450d42
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5f2bc9ad1b08bd657c1cf7d574a80aa3c4bce0af b/net/data/fuzzer_data/cookies/5f2bc9ad1b08bd657c1cf7d574a80aa3c4bce0af
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5f2bc9ad1b08bd657c1cf7d574a80aa3c4bce0af
rename to net/data/fuzzer_data/cookies/5f2bc9ad1b08bd657c1cf7d574a80aa3c4bce0af
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/5f4be9aba695bcd285b5556d09f72dcf47171e83 b/net/data/fuzzer_data/cookies/5f4be9aba695bcd285b5556d09f72dcf47171e83
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/5f4be9aba695bcd285b5556d09f72dcf47171e83
rename to net/data/fuzzer_data/cookies/5f4be9aba695bcd285b5556d09f72dcf47171e83
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/60d5bdd3be81fb3223919e405ec217b51658573a b/net/data/fuzzer_data/cookies/60d5bdd3be81fb3223919e405ec217b51658573a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/60d5bdd3be81fb3223919e405ec217b51658573a
rename to net/data/fuzzer_data/cookies/60d5bdd3be81fb3223919e405ec217b51658573a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/63aff027c3be93e49a859f283eaf399f4ff4a047 b/net/data/fuzzer_data/cookies/63aff027c3be93e49a859f283eaf399f4ff4a047
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/63aff027c3be93e49a859f283eaf399f4ff4a047
rename to net/data/fuzzer_data/cookies/63aff027c3be93e49a859f283eaf399f4ff4a047
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/64073c0a644c5a0c8bd726017654ee383632be99 b/net/data/fuzzer_data/cookies/64073c0a644c5a0c8bd726017654ee383632be99
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/64073c0a644c5a0c8bd726017654ee383632be99
rename to net/data/fuzzer_data/cookies/64073c0a644c5a0c8bd726017654ee383632be99
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6442aec070c4820805d864f353b1d1b5e345b726 b/net/data/fuzzer_data/cookies/6442aec070c4820805d864f353b1d1b5e345b726
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6442aec070c4820805d864f353b1d1b5e345b726
rename to net/data/fuzzer_data/cookies/6442aec070c4820805d864f353b1d1b5e345b726
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/654546257dc2678ee6c6c2e4b12606b63f22dc26 b/net/data/fuzzer_data/cookies/654546257dc2678ee6c6c2e4b12606b63f22dc26
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/654546257dc2678ee6c6c2e4b12606b63f22dc26
rename to net/data/fuzzer_data/cookies/654546257dc2678ee6c6c2e4b12606b63f22dc26
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/66c4df28a485f3000a3d53ac912d933604ea4adb b/net/data/fuzzer_data/cookies/66c4df28a485f3000a3d53ac912d933604ea4adb
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/66c4df28a485f3000a3d53ac912d933604ea4adb
rename to net/data/fuzzer_data/cookies/66c4df28a485f3000a3d53ac912d933604ea4adb
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/66ff8ee9c7520c24a81b5ba20d4e19464338af8b b/net/data/fuzzer_data/cookies/66ff8ee9c7520c24a81b5ba20d4e19464338af8b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/66ff8ee9c7520c24a81b5ba20d4e19464338af8b
rename to net/data/fuzzer_data/cookies/66ff8ee9c7520c24a81b5ba20d4e19464338af8b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/67b8af2d8181b851bd9d42bc7679b522b6518e83 b/net/data/fuzzer_data/cookies/67b8af2d8181b851bd9d42bc7679b522b6518e83
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/67b8af2d8181b851bd9d42bc7679b522b6518e83
rename to net/data/fuzzer_data/cookies/67b8af2d8181b851bd9d42bc7679b522b6518e83
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/684aba2bacbb9573889886c402b4643df839a6db b/net/data/fuzzer_data/cookies/684aba2bacbb9573889886c402b4643df839a6db
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/684aba2bacbb9573889886c402b4643df839a6db
rename to net/data/fuzzer_data/cookies/684aba2bacbb9573889886c402b4643df839a6db
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/68d44311484a876232c13354a48d4a9d8a56a93d b/net/data/fuzzer_data/cookies/68d44311484a876232c13354a48d4a9d8a56a93d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/68d44311484a876232c13354a48d4a9d8a56a93d
rename to net/data/fuzzer_data/cookies/68d44311484a876232c13354a48d4a9d8a56a93d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/699618333cda1edee5e0197c432e7eb57957919f b/net/data/fuzzer_data/cookies/699618333cda1edee5e0197c432e7eb57957919f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/699618333cda1edee5e0197c432e7eb57957919f
rename to net/data/fuzzer_data/cookies/699618333cda1edee5e0197c432e7eb57957919f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6c27b97c4d8e88c0384f49275c12ca8dfec3f2b1 b/net/data/fuzzer_data/cookies/6c27b97c4d8e88c0384f49275c12ca8dfec3f2b1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6c27b97c4d8e88c0384f49275c12ca8dfec3f2b1
rename to net/data/fuzzer_data/cookies/6c27b97c4d8e88c0384f49275c12ca8dfec3f2b1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6caf8ec2667c504fe740589d8724225cb5c066af b/net/data/fuzzer_data/cookies/6caf8ec2667c504fe740589d8724225cb5c066af
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6caf8ec2667c504fe740589d8724225cb5c066af
rename to net/data/fuzzer_data/cookies/6caf8ec2667c504fe740589d8724225cb5c066af
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6cdcd6da0cb200c3990b4261dbd37c84751f6a19 b/net/data/fuzzer_data/cookies/6cdcd6da0cb200c3990b4261dbd37c84751f6a19
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6cdcd6da0cb200c3990b4261dbd37c84751f6a19
rename to net/data/fuzzer_data/cookies/6cdcd6da0cb200c3990b4261dbd37c84751f6a19
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6deb439d6eaa004c80c84b949dd24cd6620be600 b/net/data/fuzzer_data/cookies/6deb439d6eaa004c80c84b949dd24cd6620be600
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6deb439d6eaa004c80c84b949dd24cd6620be600
rename to net/data/fuzzer_data/cookies/6deb439d6eaa004c80c84b949dd24cd6620be600
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6ee1ce43df2be4847406862ff4d71586bb0f224d b/net/data/fuzzer_data/cookies/6ee1ce43df2be4847406862ff4d71586bb0f224d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6ee1ce43df2be4847406862ff4d71586bb0f224d
rename to net/data/fuzzer_data/cookies/6ee1ce43df2be4847406862ff4d71586bb0f224d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6f7ac6743f97cc2ac23e0a02f48c25b9f47a4df7 b/net/data/fuzzer_data/cookies/6f7ac6743f97cc2ac23e0a02f48c25b9f47a4df7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6f7ac6743f97cc2ac23e0a02f48c25b9f47a4df7
rename to net/data/fuzzer_data/cookies/6f7ac6743f97cc2ac23e0a02f48c25b9f47a4df7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6fb957ea7bdf44acafa9341f0dc870e00312fbfd b/net/data/fuzzer_data/cookies/6fb957ea7bdf44acafa9341f0dc870e00312fbfd
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6fb957ea7bdf44acafa9341f0dc870e00312fbfd
rename to net/data/fuzzer_data/cookies/6fb957ea7bdf44acafa9341f0dc870e00312fbfd
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/6fba37a06b13f6dfc8d2b54ceb60adf7fab51d30 b/net/data/fuzzer_data/cookies/6fba37a06b13f6dfc8d2b54ceb60adf7fab51d30
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/6fba37a06b13f6dfc8d2b54ceb60adf7fab51d30
rename to net/data/fuzzer_data/cookies/6fba37a06b13f6dfc8d2b54ceb60adf7fab51d30
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/712129608f08467f6b10733824b4a71ed722e0a9 b/net/data/fuzzer_data/cookies/712129608f08467f6b10733824b4a71ed722e0a9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/712129608f08467f6b10733824b4a71ed722e0a9
rename to net/data/fuzzer_data/cookies/712129608f08467f6b10733824b4a71ed722e0a9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/72c7e26ca5ddcde6c7af72f6d6809a273cb502c6 b/net/data/fuzzer_data/cookies/72c7e26ca5ddcde6c7af72f6d6809a273cb502c6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/72c7e26ca5ddcde6c7af72f6d6809a273cb502c6
rename to net/data/fuzzer_data/cookies/72c7e26ca5ddcde6c7af72f6d6809a273cb502c6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/799e1331771bae0c65ba8ebf1a9217fdd3c7d6e1 b/net/data/fuzzer_data/cookies/799e1331771bae0c65ba8ebf1a9217fdd3c7d6e1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/799e1331771bae0c65ba8ebf1a9217fdd3c7d6e1
rename to net/data/fuzzer_data/cookies/799e1331771bae0c65ba8ebf1a9217fdd3c7d6e1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/79b5e3f7b48148dcb745743e35dbd007cda9fdf5 b/net/data/fuzzer_data/cookies/79b5e3f7b48148dcb745743e35dbd007cda9fdf5
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/79b5e3f7b48148dcb745743e35dbd007cda9fdf5
rename to net/data/fuzzer_data/cookies/79b5e3f7b48148dcb745743e35dbd007cda9fdf5
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7a95bb483c6b50d6ab8c5311f5a232179ca6d2a4 b/net/data/fuzzer_data/cookies/7a95bb483c6b50d6ab8c5311f5a232179ca6d2a4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7a95bb483c6b50d6ab8c5311f5a232179ca6d2a4
rename to net/data/fuzzer_data/cookies/7a95bb483c6b50d6ab8c5311f5a232179ca6d2a4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7bbb7121c24214cb9dc8c9817f043409ba2f02ac b/net/data/fuzzer_data/cookies/7bbb7121c24214cb9dc8c9817f043409ba2f02ac
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7bbb7121c24214cb9dc8c9817f043409ba2f02ac
rename to net/data/fuzzer_data/cookies/7bbb7121c24214cb9dc8c9817f043409ba2f02ac
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7d6a16550506d166e4aa837f14624dd8674f1a5c b/net/data/fuzzer_data/cookies/7d6a16550506d166e4aa837f14624dd8674f1a5c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7d6a16550506d166e4aa837f14624dd8674f1a5c
rename to net/data/fuzzer_data/cookies/7d6a16550506d166e4aa837f14624dd8674f1a5c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7df362478575dcf2483209b8f57bba31d0964319 b/net/data/fuzzer_data/cookies/7df362478575dcf2483209b8f57bba31d0964319
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7df362478575dcf2483209b8f57bba31d0964319
rename to net/data/fuzzer_data/cookies/7df362478575dcf2483209b8f57bba31d0964319
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7e57c07b2c66a4d13931f5c7b6cf089355d6a322 b/net/data/fuzzer_data/cookies/7e57c07b2c66a4d13931f5c7b6cf089355d6a322
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7e57c07b2c66a4d13931f5c7b6cf089355d6a322
rename to net/data/fuzzer_data/cookies/7e57c07b2c66a4d13931f5c7b6cf089355d6a322
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/7e7bfb391ef30a6ce2e73d2fd6cbf6da2892ac0b b/net/data/fuzzer_data/cookies/7e7bfb391ef30a6ce2e73d2fd6cbf6da2892ac0b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/7e7bfb391ef30a6ce2e73d2fd6cbf6da2892ac0b
rename to net/data/fuzzer_data/cookies/7e7bfb391ef30a6ce2e73d2fd6cbf6da2892ac0b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/83f95b16737e62733ca9dd33615c5b4b8691e1da b/net/data/fuzzer_data/cookies/83f95b16737e62733ca9dd33615c5b4b8691e1da
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/83f95b16737e62733ca9dd33615c5b4b8691e1da
rename to net/data/fuzzer_data/cookies/83f95b16737e62733ca9dd33615c5b4b8691e1da
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/8549e6688c60c294b832f113e941158ea7c50d29 b/net/data/fuzzer_data/cookies/8549e6688c60c294b832f113e941158ea7c50d29
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/8549e6688c60c294b832f113e941158ea7c50d29
rename to net/data/fuzzer_data/cookies/8549e6688c60c294b832f113e941158ea7c50d29
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/87c7756c358d3e07c3905fd5b8e8422554312417 b/net/data/fuzzer_data/cookies/87c7756c358d3e07c3905fd5b8e8422554312417
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/87c7756c358d3e07c3905fd5b8e8422554312417
rename to net/data/fuzzer_data/cookies/87c7756c358d3e07c3905fd5b8e8422554312417
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/883d2f0ea7240fe7aa628c68f07f64602fbed739 b/net/data/fuzzer_data/cookies/883d2f0ea7240fe7aa628c68f07f64602fbed739
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/883d2f0ea7240fe7aa628c68f07f64602fbed739
rename to net/data/fuzzer_data/cookies/883d2f0ea7240fe7aa628c68f07f64602fbed739
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/88d246284f834fc97cbf96e70d276a2c6b9fc1e9 b/net/data/fuzzer_data/cookies/88d246284f834fc97cbf96e70d276a2c6b9fc1e9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/88d246284f834fc97cbf96e70d276a2c6b9fc1e9
rename to net/data/fuzzer_data/cookies/88d246284f834fc97cbf96e70d276a2c6b9fc1e9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/8a1ebe0170c6f65078913460be67226aa57e99ef b/net/data/fuzzer_data/cookies/8a1ebe0170c6f65078913460be67226aa57e99ef
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/8a1ebe0170c6f65078913460be67226aa57e99ef
rename to net/data/fuzzer_data/cookies/8a1ebe0170c6f65078913460be67226aa57e99ef
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/8d54ebdd62bc33498ab147f2d1148392669e52cd b/net/data/fuzzer_data/cookies/8d54ebdd62bc33498ab147f2d1148392669e52cd
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/8d54ebdd62bc33498ab147f2d1148392669e52cd
rename to net/data/fuzzer_data/cookies/8d54ebdd62bc33498ab147f2d1148392669e52cd
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/8d9420f68cd0e613da95bc4ad29b2b411be226e6 b/net/data/fuzzer_data/cookies/8d9420f68cd0e613da95bc4ad29b2b411be226e6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/8d9420f68cd0e613da95bc4ad29b2b411be226e6
rename to net/data/fuzzer_data/cookies/8d9420f68cd0e613da95bc4ad29b2b411be226e6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9105147695d0e6b84e7b7545499bb81e1f83ebc3 b/net/data/fuzzer_data/cookies/9105147695d0e6b84e7b7545499bb81e1f83ebc3
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9105147695d0e6b84e7b7545499bb81e1f83ebc3
rename to net/data/fuzzer_data/cookies/9105147695d0e6b84e7b7545499bb81e1f83ebc3
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/930b27bcc02ceb39a7600d2d8f2ee3f549f558c6 b/net/data/fuzzer_data/cookies/930b27bcc02ceb39a7600d2d8f2ee3f549f558c6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/930b27bcc02ceb39a7600d2d8f2ee3f549f558c6
rename to net/data/fuzzer_data/cookies/930b27bcc02ceb39a7600d2d8f2ee3f549f558c6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/966b75f066a952191642ec1e0a86b8f238e25c08 b/net/data/fuzzer_data/cookies/966b75f066a952191642ec1e0a86b8f238e25c08
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/966b75f066a952191642ec1e0a86b8f238e25c08
rename to net/data/fuzzer_data/cookies/966b75f066a952191642ec1e0a86b8f238e25c08
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/980a052dcd298c300b8a85eea0f48ab95ebda001 b/net/data/fuzzer_data/cookies/980a052dcd298c300b8a85eea0f48ab95ebda001
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/980a052dcd298c300b8a85eea0f48ab95ebda001
rename to net/data/fuzzer_data/cookies/980a052dcd298c300b8a85eea0f48ab95ebda001
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/98136a439b95331861d76e34badde628daac0ae6 b/net/data/fuzzer_data/cookies/98136a439b95331861d76e34badde628daac0ae6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/98136a439b95331861d76e34badde628daac0ae6
rename to net/data/fuzzer_data/cookies/98136a439b95331861d76e34badde628daac0ae6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9b613a83c35dc05b11fce08afcadde9471c7e11d b/net/data/fuzzer_data/cookies/9b613a83c35dc05b11fce08afcadde9471c7e11d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9b613a83c35dc05b11fce08afcadde9471c7e11d
rename to net/data/fuzzer_data/cookies/9b613a83c35dc05b11fce08afcadde9471c7e11d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9baaac27c51a8e252694fcfee5de56a959f58812 b/net/data/fuzzer_data/cookies/9baaac27c51a8e252694fcfee5de56a959f58812
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9baaac27c51a8e252694fcfee5de56a959f58812
rename to net/data/fuzzer_data/cookies/9baaac27c51a8e252694fcfee5de56a959f58812
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9c5bffd6e16ab51ab600ffd41bd673d55b73227f b/net/data/fuzzer_data/cookies/9c5bffd6e16ab51ab600ffd41bd673d55b73227f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9c5bffd6e16ab51ab600ffd41bd673d55b73227f
rename to net/data/fuzzer_data/cookies/9c5bffd6e16ab51ab600ffd41bd673d55b73227f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9daf222acc36cfe241f0e660431bb5760aab59f6 b/net/data/fuzzer_data/cookies/9daf222acc36cfe241f0e660431bb5760aab59f6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9daf222acc36cfe241f0e660431bb5760aab59f6
rename to net/data/fuzzer_data/cookies/9daf222acc36cfe241f0e660431bb5760aab59f6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9e5dc9555de669ac997ae888fae3548662ffa508 b/net/data/fuzzer_data/cookies/9e5dc9555de669ac997ae888fae3548662ffa508
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9e5dc9555de669ac997ae888fae3548662ffa508
rename to net/data/fuzzer_data/cookies/9e5dc9555de669ac997ae888fae3548662ffa508
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/9f686fa12180f8aae8c8a696eb3525ff18620fea b/net/data/fuzzer_data/cookies/9f686fa12180f8aae8c8a696eb3525ff18620fea
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/9f686fa12180f8aae8c8a696eb3525ff18620fea
rename to net/data/fuzzer_data/cookies/9f686fa12180f8aae8c8a696eb3525ff18620fea
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a006c363ccdbc4121f0734bd7f93898bf0101c5e b/net/data/fuzzer_data/cookies/a006c363ccdbc4121f0734bd7f93898bf0101c5e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a006c363ccdbc4121f0734bd7f93898bf0101c5e
rename to net/data/fuzzer_data/cookies/a006c363ccdbc4121f0734bd7f93898bf0101c5e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a2b111008c37bde96280f6eb34f1cc182edba9c7 b/net/data/fuzzer_data/cookies/a2b111008c37bde96280f6eb34f1cc182edba9c7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a2b111008c37bde96280f6eb34f1cc182edba9c7
rename to net/data/fuzzer_data/cookies/a2b111008c37bde96280f6eb34f1cc182edba9c7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a3812a8554575845ec323258c1f4cc72529ae7a1 b/net/data/fuzzer_data/cookies/a3812a8554575845ec323258c1f4cc72529ae7a1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a3812a8554575845ec323258c1f4cc72529ae7a1
rename to net/data/fuzzer_data/cookies/a3812a8554575845ec323258c1f4cc72529ae7a1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a387680027e3c79201c6ecd9c1598ab70da687d0 b/net/data/fuzzer_data/cookies/a387680027e3c79201c6ecd9c1598ab70da687d0
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a387680027e3c79201c6ecd9c1598ab70da687d0
rename to net/data/fuzzer_data/cookies/a387680027e3c79201c6ecd9c1598ab70da687d0
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a5e269a9df8c9bd955bba6a55fee5a7389d5083a b/net/data/fuzzer_data/cookies/a5e269a9df8c9bd955bba6a55fee5a7389d5083a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a5e269a9df8c9bd955bba6a55fee5a7389d5083a
rename to net/data/fuzzer_data/cookies/a5e269a9df8c9bd955bba6a55fee5a7389d5083a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a602e6486b4f1d610becb8fc5e516e732f1f3981 b/net/data/fuzzer_data/cookies/a602e6486b4f1d610becb8fc5e516e732f1f3981
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a602e6486b4f1d610becb8fc5e516e732f1f3981
rename to net/data/fuzzer_data/cookies/a602e6486b4f1d610becb8fc5e516e732f1f3981
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a967d0eff334c245ba15b2df413b191c8d6f4c06 b/net/data/fuzzer_data/cookies/a967d0eff334c245ba15b2df413b191c8d6f4c06
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a967d0eff334c245ba15b2df413b191c8d6f4c06
rename to net/data/fuzzer_data/cookies/a967d0eff334c245ba15b2df413b191c8d6f4c06
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/a9ae8af071d9a9e33687e99a9f7c1257a30c33b0 b/net/data/fuzzer_data/cookies/a9ae8af071d9a9e33687e99a9f7c1257a30c33b0
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/a9ae8af071d9a9e33687e99a9f7c1257a30c33b0
rename to net/data/fuzzer_data/cookies/a9ae8af071d9a9e33687e99a9f7c1257a30c33b0
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/aa8c3612aa5d1fded530841fceea34368430b1d9 b/net/data/fuzzer_data/cookies/aa8c3612aa5d1fded530841fceea34368430b1d9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/aa8c3612aa5d1fded530841fceea34368430b1d9
rename to net/data/fuzzer_data/cookies/aa8c3612aa5d1fded530841fceea34368430b1d9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ab45fd913c24c5b0c8777d53a5f2a5ed97d4b33a b/net/data/fuzzer_data/cookies/ab45fd913c24c5b0c8777d53a5f2a5ed97d4b33a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ab45fd913c24c5b0c8777d53a5f2a5ed97d4b33a
rename to net/data/fuzzer_data/cookies/ab45fd913c24c5b0c8777d53a5f2a5ed97d4b33a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/abd345c64fcdda7d228a16452d1b0fd0fdf87c92 b/net/data/fuzzer_data/cookies/abd345c64fcdda7d228a16452d1b0fd0fdf87c92
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/abd345c64fcdda7d228a16452d1b0fd0fdf87c92
rename to net/data/fuzzer_data/cookies/abd345c64fcdda7d228a16452d1b0fd0fdf87c92
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ae577cfcac4a264d2fdcfd10672ed8660a3744a9 b/net/data/fuzzer_data/cookies/ae577cfcac4a264d2fdcfd10672ed8660a3744a9
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ae577cfcac4a264d2fdcfd10672ed8660a3744a9
rename to net/data/fuzzer_data/cookies/ae577cfcac4a264d2fdcfd10672ed8660a3744a9
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/aed35c0ef545c3208e2704126951375145b216e1 b/net/data/fuzzer_data/cookies/aed35c0ef545c3208e2704126951375145b216e1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/aed35c0ef545c3208e2704126951375145b216e1
rename to net/data/fuzzer_data/cookies/aed35c0ef545c3208e2704126951375145b216e1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b059f387b1c09a7eceeaa81b25081bcc66063f47 b/net/data/fuzzer_data/cookies/b059f387b1c09a7eceeaa81b25081bcc66063f47
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b059f387b1c09a7eceeaa81b25081bcc66063f47
rename to net/data/fuzzer_data/cookies/b059f387b1c09a7eceeaa81b25081bcc66063f47
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b0df406eea85a70bb1324627f2ee8c90a36da71c b/net/data/fuzzer_data/cookies/b0df406eea85a70bb1324627f2ee8c90a36da71c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b0df406eea85a70bb1324627f2ee8c90a36da71c
rename to net/data/fuzzer_data/cookies/b0df406eea85a70bb1324627f2ee8c90a36da71c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b1a43c3e4b8555d4852d6753d9f4591585d56f12 b/net/data/fuzzer_data/cookies/b1a43c3e4b8555d4852d6753d9f4591585d56f12
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b1a43c3e4b8555d4852d6753d9f4591585d56f12
rename to net/data/fuzzer_data/cookies/b1a43c3e4b8555d4852d6753d9f4591585d56f12
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b3598cc6126ca46c297fee25a1126891da3248fa b/net/data/fuzzer_data/cookies/b3598cc6126ca46c297fee25a1126891da3248fa
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b3598cc6126ca46c297fee25a1126891da3248fa
rename to net/data/fuzzer_data/cookies/b3598cc6126ca46c297fee25a1126891da3248fa
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b4a4b331511573b1cba6212bcfcfcfce76c9a1d2 b/net/data/fuzzer_data/cookies/b4a4b331511573b1cba6212bcfcfcfce76c9a1d2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b4a4b331511573b1cba6212bcfcfcfce76c9a1d2
rename to net/data/fuzzer_data/cookies/b4a4b331511573b1cba6212bcfcfcfce76c9a1d2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b61ce67a71cdca8adde870205457ddc1b34726cf b/net/data/fuzzer_data/cookies/b61ce67a71cdca8adde870205457ddc1b34726cf
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b61ce67a71cdca8adde870205457ddc1b34726cf
rename to net/data/fuzzer_data/cookies/b61ce67a71cdca8adde870205457ddc1b34726cf
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b6b88352b38b73b8251b9ee3a49e87013678c2a8 b/net/data/fuzzer_data/cookies/b6b88352b38b73b8251b9ee3a49e87013678c2a8
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b6b88352b38b73b8251b9ee3a49e87013678c2a8
rename to net/data/fuzzer_data/cookies/b6b88352b38b73b8251b9ee3a49e87013678c2a8
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/b9068d648a12bdd59916d36aabaa5028d428ca3a b/net/data/fuzzer_data/cookies/b9068d648a12bdd59916d36aabaa5028d428ca3a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/b9068d648a12bdd59916d36aabaa5028d428ca3a
rename to net/data/fuzzer_data/cookies/b9068d648a12bdd59916d36aabaa5028d428ca3a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/bab3e37371e0e1b75eebb05a72268c5ff1899c19 b/net/data/fuzzer_data/cookies/bab3e37371e0e1b75eebb05a72268c5ff1899c19
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/bab3e37371e0e1b75eebb05a72268c5ff1899c19
rename to net/data/fuzzer_data/cookies/bab3e37371e0e1b75eebb05a72268c5ff1899c19
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/baf73c2f692eab8f7a763b6143c1785c94ddce0f b/net/data/fuzzer_data/cookies/baf73c2f692eab8f7a763b6143c1785c94ddce0f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/baf73c2f692eab8f7a763b6143c1785c94ddce0f
rename to net/data/fuzzer_data/cookies/baf73c2f692eab8f7a763b6143c1785c94ddce0f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/bc6b09cf7a516ebd8e871816dea62c233e62cfbf b/net/data/fuzzer_data/cookies/bc6b09cf7a516ebd8e871816dea62c233e62cfbf
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/bc6b09cf7a516ebd8e871816dea62c233e62cfbf
rename to net/data/fuzzer_data/cookies/bc6b09cf7a516ebd8e871816dea62c233e62cfbf
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/bd202c1f7047d50eb61966b03f7ad22b5ae2786b b/net/data/fuzzer_data/cookies/bd202c1f7047d50eb61966b03f7ad22b5ae2786b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/bd202c1f7047d50eb61966b03f7ad22b5ae2786b
rename to net/data/fuzzer_data/cookies/bd202c1f7047d50eb61966b03f7ad22b5ae2786b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/bde300efbe573f13a8cb6a31c284f5884558a083 b/net/data/fuzzer_data/cookies/bde300efbe573f13a8cb6a31c284f5884558a083
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/bde300efbe573f13a8cb6a31c284f5884558a083
rename to net/data/fuzzer_data/cookies/bde300efbe573f13a8cb6a31c284f5884558a083
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/bee3b3eab3a566eead02de9473d3987ee418918e b/net/data/fuzzer_data/cookies/bee3b3eab3a566eead02de9473d3987ee418918e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/bee3b3eab3a566eead02de9473d3987ee418918e
rename to net/data/fuzzer_data/cookies/bee3b3eab3a566eead02de9473d3987ee418918e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c035fa19f7758f1e2b24f93bd0af005a35f64d51 b/net/data/fuzzer_data/cookies/c035fa19f7758f1e2b24f93bd0af005a35f64d51
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c035fa19f7758f1e2b24f93bd0af005a35f64d51
rename to net/data/fuzzer_data/cookies/c035fa19f7758f1e2b24f93bd0af005a35f64d51
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c16921c200c10c04d94f858c0061b6807b52b9d6 b/net/data/fuzzer_data/cookies/c16921c200c10c04d94f858c0061b6807b52b9d6
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c16921c200c10c04d94f858c0061b6807b52b9d6
rename to net/data/fuzzer_data/cookies/c16921c200c10c04d94f858c0061b6807b52b9d6
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c1a11b69a334883638a59a9a4f46ea8011ca62bd b/net/data/fuzzer_data/cookies/c1a11b69a334883638a59a9a4f46ea8011ca62bd
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c1a11b69a334883638a59a9a4f46ea8011ca62bd
rename to net/data/fuzzer_data/cookies/c1a11b69a334883638a59a9a4f46ea8011ca62bd
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c1e5431d0d29b6c1bf7e43195001edd6ddc16930 b/net/data/fuzzer_data/cookies/c1e5431d0d29b6c1bf7e43195001edd6ddc16930
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c1e5431d0d29b6c1bf7e43195001edd6ddc16930
rename to net/data/fuzzer_data/cookies/c1e5431d0d29b6c1bf7e43195001edd6ddc16930
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5bb577b01c9d403ac38cc096f68e9cf636a70a5 b/net/data/fuzzer_data/cookies/c5bb577b01c9d403ac38cc096f68e9cf636a70a5
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5bb577b01c9d403ac38cc096f68e9cf636a70a5
rename to net/data/fuzzer_data/cookies/c5bb577b01c9d403ac38cc096f68e9cf636a70a5
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5c4788bc7ee1890b8e9d93c2663b1a218ac887e b/net/data/fuzzer_data/cookies/c5c4788bc7ee1890b8e9d93c2663b1a218ac887e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5c4788bc7ee1890b8e9d93c2663b1a218ac887e
rename to net/data/fuzzer_data/cookies/c5c4788bc7ee1890b8e9d93c2663b1a218ac887e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5e3f4980f8fae067de684bb1145f8f29bccd4ff b/net/data/fuzzer_data/cookies/c5e3f4980f8fae067de684bb1145f8f29bccd4ff
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c5e3f4980f8fae067de684bb1145f8f29bccd4ff
rename to net/data/fuzzer_data/cookies/c5e3f4980f8fae067de684bb1145f8f29bccd4ff
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c6cd3f070eae98856c1e258950fcc289b683a19b b/net/data/fuzzer_data/cookies/c6cd3f070eae98856c1e258950fcc289b683a19b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c6cd3f070eae98856c1e258950fcc289b683a19b
rename to net/data/fuzzer_data/cookies/c6cd3f070eae98856c1e258950fcc289b683a19b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c7977a8a3aefa635c80cfa8bca2d1fb3d3e26a25 b/net/data/fuzzer_data/cookies/c7977a8a3aefa635c80cfa8bca2d1fb3d3e26a25
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c7977a8a3aefa635c80cfa8bca2d1fb3d3e26a25
rename to net/data/fuzzer_data/cookies/c7977a8a3aefa635c80cfa8bca2d1fb3d3e26a25
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c848478dfa63274d82e5185d73d24b7e1b67744e b/net/data/fuzzer_data/cookies/c848478dfa63274d82e5185d73d24b7e1b67744e
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c848478dfa63274d82e5185d73d24b7e1b67744e
rename to net/data/fuzzer_data/cookies/c848478dfa63274d82e5185d73d24b7e1b67744e
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/c9781b22777b843d2edc9c008d09a0b7ce18c63c b/net/data/fuzzer_data/cookies/c9781b22777b843d2edc9c008d09a0b7ce18c63c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/c9781b22777b843d2edc9c008d09a0b7ce18c63c
rename to net/data/fuzzer_data/cookies/c9781b22777b843d2edc9c008d09a0b7ce18c63c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ca44506cddacce4558ccd4e988e9097d23b62c4b b/net/data/fuzzer_data/cookies/ca44506cddacce4558ccd4e988e9097d23b62c4b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ca44506cddacce4558ccd4e988e9097d23b62c4b
rename to net/data/fuzzer_data/cookies/ca44506cddacce4558ccd4e988e9097d23b62c4b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ce0a43bed8d76d5e1345efb0dffd87760de01419 b/net/data/fuzzer_data/cookies/ce0a43bed8d76d5e1345efb0dffd87760de01419
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ce0a43bed8d76d5e1345efb0dffd87760de01419
rename to net/data/fuzzer_data/cookies/ce0a43bed8d76d5e1345efb0dffd87760de01419
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d067e2ce2fb24e91781a9d2dba39789bc640ba58 b/net/data/fuzzer_data/cookies/d067e2ce2fb24e91781a9d2dba39789bc640ba58
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d067e2ce2fb24e91781a9d2dba39789bc640ba58
rename to net/data/fuzzer_data/cookies/d067e2ce2fb24e91781a9d2dba39789bc640ba58
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d1de6143e8f6bf4dd6cdeb221500978e574a373f b/net/data/fuzzer_data/cookies/d1de6143e8f6bf4dd6cdeb221500978e574a373f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d1de6143e8f6bf4dd6cdeb221500978e574a373f
rename to net/data/fuzzer_data/cookies/d1de6143e8f6bf4dd6cdeb221500978e574a373f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d31490cc2692f21b7ef0cee6d1b55d2a6f2774ce b/net/data/fuzzer_data/cookies/d31490cc2692f21b7ef0cee6d1b55d2a6f2774ce
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d31490cc2692f21b7ef0cee6d1b55d2a6f2774ce
rename to net/data/fuzzer_data/cookies/d31490cc2692f21b7ef0cee6d1b55d2a6f2774ce
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d3ec18e49be8b10c8d7e139ef542e2d503ab74bf b/net/data/fuzzer_data/cookies/d3ec18e49be8b10c8d7e139ef542e2d503ab74bf
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d3ec18e49be8b10c8d7e139ef542e2d503ab74bf
rename to net/data/fuzzer_data/cookies/d3ec18e49be8b10c8d7e139ef542e2d503ab74bf
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d4a65f0a8a24afc644a0ad256a1f40ecddf744d7 b/net/data/fuzzer_data/cookies/d4a65f0a8a24afc644a0ad256a1f40ecddf744d7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d4a65f0a8a24afc644a0ad256a1f40ecddf744d7
rename to net/data/fuzzer_data/cookies/d4a65f0a8a24afc644a0ad256a1f40ecddf744d7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d5455421116feadc30e84eb0953da843dca7d531 b/net/data/fuzzer_data/cookies/d5455421116feadc30e84eb0953da843dca7d531
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d5455421116feadc30e84eb0953da843dca7d531
rename to net/data/fuzzer_data/cookies/d5455421116feadc30e84eb0953da843dca7d531
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d5b0ac144a5f4f4ca14dd76540a705d3e6ff040b b/net/data/fuzzer_data/cookies/d5b0ac144a5f4f4ca14dd76540a705d3e6ff040b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d5b0ac144a5f4f4ca14dd76540a705d3e6ff040b
rename to net/data/fuzzer_data/cookies/d5b0ac144a5f4f4ca14dd76540a705d3e6ff040b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/d6292a8df3a8870b9e0f79d2e00f28747032313c b/net/data/fuzzer_data/cookies/d6292a8df3a8870b9e0f79d2e00f28747032313c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/d6292a8df3a8870b9e0f79d2e00f28747032313c
rename to net/data/fuzzer_data/cookies/d6292a8df3a8870b9e0f79d2e00f28747032313c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/da71635721b412900255c668d89658436ae893c0 b/net/data/fuzzer_data/cookies/da71635721b412900255c668d89658436ae893c0
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/da71635721b412900255c668d89658436ae893c0
rename to net/data/fuzzer_data/cookies/da71635721b412900255c668d89658436ae893c0
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/daa754829b5cf410d82eb1a1347912907bdd4fe2 b/net/data/fuzzer_data/cookies/daa754829b5cf410d82eb1a1347912907bdd4fe2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/daa754829b5cf410d82eb1a1347912907bdd4fe2
rename to net/data/fuzzer_data/cookies/daa754829b5cf410d82eb1a1347912907bdd4fe2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/db21ed57b9957be739e288f3f3df7e37469fd4c5 b/net/data/fuzzer_data/cookies/db21ed57b9957be739e288f3f3df7e37469fd4c5
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/db21ed57b9957be739e288f3f3df7e37469fd4c5
rename to net/data/fuzzer_data/cookies/db21ed57b9957be739e288f3f3df7e37469fd4c5
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/de5f6cb9286f0faa29e22afae207e842f7203f68 b/net/data/fuzzer_data/cookies/de5f6cb9286f0faa29e22afae207e842f7203f68
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/de5f6cb9286f0faa29e22afae207e842f7203f68
rename to net/data/fuzzer_data/cookies/de5f6cb9286f0faa29e22afae207e842f7203f68
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/de98b6c77ee3b3568754214cdc77dfd1d1cc1fb7 b/net/data/fuzzer_data/cookies/de98b6c77ee3b3568754214cdc77dfd1d1cc1fb7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/de98b6c77ee3b3568754214cdc77dfd1d1cc1fb7
rename to net/data/fuzzer_data/cookies/de98b6c77ee3b3568754214cdc77dfd1d1cc1fb7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/deeb5777a37fb09150c1dcd9ed8178fcfc2f5965 b/net/data/fuzzer_data/cookies/deeb5777a37fb09150c1dcd9ed8178fcfc2f5965
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/deeb5777a37fb09150c1dcd9ed8178fcfc2f5965
rename to net/data/fuzzer_data/cookies/deeb5777a37fb09150c1dcd9ed8178fcfc2f5965
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/df73098143170c180a39a623c462b7543f0492ad b/net/data/fuzzer_data/cookies/df73098143170c180a39a623c462b7543f0492ad
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/df73098143170c180a39a623c462b7543f0492ad
rename to net/data/fuzzer_data/cookies/df73098143170c180a39a623c462b7543f0492ad
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e04f62817d06ed80ce6f156e5a6bc77bb5639af1 b/net/data/fuzzer_data/cookies/e04f62817d06ed80ce6f156e5a6bc77bb5639af1
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e04f62817d06ed80ce6f156e5a6bc77bb5639af1
rename to net/data/fuzzer_data/cookies/e04f62817d06ed80ce6f156e5a6bc77bb5639af1
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e17f34e9fca3b7abcdf00766120e1f11d62ba0f4 b/net/data/fuzzer_data/cookies/e17f34e9fca3b7abcdf00766120e1f11d62ba0f4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e17f34e9fca3b7abcdf00766120e1f11d62ba0f4
rename to net/data/fuzzer_data/cookies/e17f34e9fca3b7abcdf00766120e1f11d62ba0f4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e1992da7965c21c43dd232a1a66c0ae9e65419c7 b/net/data/fuzzer_data/cookies/e1992da7965c21c43dd232a1a66c0ae9e65419c7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e1992da7965c21c43dd232a1a66c0ae9e65419c7
rename to net/data/fuzzer_data/cookies/e1992da7965c21c43dd232a1a66c0ae9e65419c7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e1af2e3bef5a200a4759be73c2cf4483826c5cda b/net/data/fuzzer_data/cookies/e1af2e3bef5a200a4759be73c2cf4483826c5cda
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e1af2e3bef5a200a4759be73c2cf4483826c5cda
rename to net/data/fuzzer_data/cookies/e1af2e3bef5a200a4759be73c2cf4483826c5cda
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e40231ef2f3143dde83067ed24d47313c758a745 b/net/data/fuzzer_data/cookies/e40231ef2f3143dde83067ed24d47313c758a745
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e40231ef2f3143dde83067ed24d47313c758a745
rename to net/data/fuzzer_data/cookies/e40231ef2f3143dde83067ed24d47313c758a745
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e486dc80398ed1368e2f14543a7d262a823faa33 b/net/data/fuzzer_data/cookies/e486dc80398ed1368e2f14543a7d262a823faa33
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e486dc80398ed1368e2f14543a7d262a823faa33
rename to net/data/fuzzer_data/cookies/e486dc80398ed1368e2f14543a7d262a823faa33
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e60d6d7872d1d70859c8d26ee4050c47a2eaf011 b/net/data/fuzzer_data/cookies/e60d6d7872d1d70859c8d26ee4050c47a2eaf011
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e60d6d7872d1d70859c8d26ee4050c47a2eaf011
rename to net/data/fuzzer_data/cookies/e60d6d7872d1d70859c8d26ee4050c47a2eaf011
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e61277ff2502bc356df7870b2b98b2a8252f166c b/net/data/fuzzer_data/cookies/e61277ff2502bc356df7870b2b98b2a8252f166c
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e61277ff2502bc356df7870b2b98b2a8252f166c
rename to net/data/fuzzer_data/cookies/e61277ff2502bc356df7870b2b98b2a8252f166c
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/e7e83533a247e20817f9aecdbabee3b8c0c8a0e4 b/net/data/fuzzer_data/cookies/e7e83533a247e20817f9aecdbabee3b8c0c8a0e4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/e7e83533a247e20817f9aecdbabee3b8c0c8a0e4
rename to net/data/fuzzer_data/cookies/e7e83533a247e20817f9aecdbabee3b8c0c8a0e4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ea08a08df36906fea11d1bd082cfd9945c72869a b/net/data/fuzzer_data/cookies/ea08a08df36906fea11d1bd082cfd9945c72869a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ea08a08df36906fea11d1bd082cfd9945c72869a
rename to net/data/fuzzer_data/cookies/ea08a08df36906fea11d1bd082cfd9945c72869a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/eb242a1d0caeb6024c7384542e8475ab301d942a b/net/data/fuzzer_data/cookies/eb242a1d0caeb6024c7384542e8475ab301d942a
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/eb242a1d0caeb6024c7384542e8475ab301d942a
rename to net/data/fuzzer_data/cookies/eb242a1d0caeb6024c7384542e8475ab301d942a
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/eb44a6fd7935b23d6c2dda809b6b7d4bbed69f65 b/net/data/fuzzer_data/cookies/eb44a6fd7935b23d6c2dda809b6b7d4bbed69f65
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/eb44a6fd7935b23d6c2dda809b6b7d4bbed69f65
rename to net/data/fuzzer_data/cookies/eb44a6fd7935b23d6c2dda809b6b7d4bbed69f65
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ee241f6d0a53870859df56ac74c603a5b5264ad4 b/net/data/fuzzer_data/cookies/ee241f6d0a53870859df56ac74c603a5b5264ad4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ee241f6d0a53870859df56ac74c603a5b5264ad4
rename to net/data/fuzzer_data/cookies/ee241f6d0a53870859df56ac74c603a5b5264ad4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/ee29ed6f1e292da3b39b23e5872f68ad3650eca7 b/net/data/fuzzer_data/cookies/ee29ed6f1e292da3b39b23e5872f68ad3650eca7
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/ee29ed6f1e292da3b39b23e5872f68ad3650eca7
rename to net/data/fuzzer_data/cookies/ee29ed6f1e292da3b39b23e5872f68ad3650eca7
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f0300c33bb43d4036e0c892ca67c959ed3a6c063 b/net/data/fuzzer_data/cookies/f0300c33bb43d4036e0c892ca67c959ed3a6c063
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f0300c33bb43d4036e0c892ca67c959ed3a6c063
rename to net/data/fuzzer_data/cookies/f0300c33bb43d4036e0c892ca67c959ed3a6c063
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f08f4732cf89fb8e213340d995842502ca8d9a19 b/net/data/fuzzer_data/cookies/f08f4732cf89fb8e213340d995842502ca8d9a19
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f08f4732cf89fb8e213340d995842502ca8d9a19
rename to net/data/fuzzer_data/cookies/f08f4732cf89fb8e213340d995842502ca8d9a19
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f0ad412595cc1472aec5cff8606542eabbfad34b b/net/data/fuzzer_data/cookies/f0ad412595cc1472aec5cff8606542eabbfad34b
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f0ad412595cc1472aec5cff8606542eabbfad34b
rename to net/data/fuzzer_data/cookies/f0ad412595cc1472aec5cff8606542eabbfad34b
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f109db547ed4bdc59a8fde6f908946ea6109cc9f b/net/data/fuzzer_data/cookies/f109db547ed4bdc59a8fde6f908946ea6109cc9f
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f109db547ed4bdc59a8fde6f908946ea6109cc9f
rename to net/data/fuzzer_data/cookies/f109db547ed4bdc59a8fde6f908946ea6109cc9f
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f13fd0f50220d38cc903dce9c8122bd59ec3f529 b/net/data/fuzzer_data/cookies/f13fd0f50220d38cc903dce9c8122bd59ec3f529
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f13fd0f50220d38cc903dce9c8122bd59ec3f529
rename to net/data/fuzzer_data/cookies/f13fd0f50220d38cc903dce9c8122bd59ec3f529
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f3dbe871488d7e3c71dc0a9c6dc6efecc669fff4 b/net/data/fuzzer_data/cookies/f3dbe871488d7e3c71dc0a9c6dc6efecc669fff4
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f3dbe871488d7e3c71dc0a9c6dc6efecc669fff4
rename to net/data/fuzzer_data/cookies/f3dbe871488d7e3c71dc0a9c6dc6efecc669fff4
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f5dbb21084f900ba67ac6d3fe80478bbe9decdbd b/net/data/fuzzer_data/cookies/f5dbb21084f900ba67ac6d3fe80478bbe9decdbd
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f5dbb21084f900ba67ac6d3fe80478bbe9decdbd
rename to net/data/fuzzer_data/cookies/f5dbb21084f900ba67ac6d3fe80478bbe9decdbd
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f83fc993626aca6ac059e791b2d7b01f3e10f969 b/net/data/fuzzer_data/cookies/f83fc993626aca6ac059e791b2d7b01f3e10f969
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f83fc993626aca6ac059e791b2d7b01f3e10f969
rename to net/data/fuzzer_data/cookies/f83fc993626aca6ac059e791b2d7b01f3e10f969
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/f8c25cdbb8d4bae5fd2eff6e35874494b52574c2 b/net/data/fuzzer_data/cookies/f8c25cdbb8d4bae5fd2eff6e35874494b52574c2
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/f8c25cdbb8d4bae5fd2eff6e35874494b52574c2
rename to net/data/fuzzer_data/cookies/f8c25cdbb8d4bae5fd2eff6e35874494b52574c2
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/fa84bb3e606d517f564607024df470f778007a95 b/net/data/fuzzer_data/cookies/fa84bb3e606d517f564607024df470f778007a95
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/fa84bb3e606d517f564607024df470f778007a95
rename to net/data/fuzzer_data/cookies/fa84bb3e606d517f564607024df470f778007a95
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/fcf781ba904f4a8ce53c00a5f1071f5bcee8a21d b/net/data/fuzzer_data/cookies/fcf781ba904f4a8ce53c00a5f1071f5bcee8a21d
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/fcf781ba904f4a8ce53c00a5f1071f5bcee8a21d
rename to net/data/fuzzer_data/cookies/fcf781ba904f4a8ce53c00a5f1071f5bcee8a21d
diff --git a/net/data/fuzzer_data/net_canonical_cookie_fuzzer/fec9232ce26d526167f5bd254706a5249090a593 b/net/data/fuzzer_data/cookies/fec9232ce26d526167f5bd254706a5249090a593
similarity index 100%
rename from net/data/fuzzer_data/net_canonical_cookie_fuzzer/fec9232ce26d526167f5bd254706a5249090a593
rename to net/data/fuzzer_data/cookies/fec9232ce26d526167f5bd254706a5249090a593
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index 0f0fe9a3..8d5753c 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -66,7 +66,7 @@
  private:
   FRIEND_TEST_ALL_PREFIXES(SSLClientSocket, SerializeNextProtos);
   // For signed_cert_timestamps_received_ and stapled_ocsp_response_received_.
-  FRIEND_TEST_ALL_PREFIXES(SSLClientSocketTest,
+  FRIEND_TEST_ALL_PREFIXES(SSLClientSocketVersionTest,
                            ConnectSignedCertTimestampsTLSExtension);
   FRIEND_TEST_ALL_PREFIXES(SSLClientSocketVersionTest,
                            ConnectSignedCertTimestampsEnablesOCSP);
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index 734b482..ff695d7 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -2877,13 +2877,15 @@
 
 // Tests that the Certificate Transparency (RFC 6962) TLS extension is
 // supported.
-TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsTLSExtension) {
+TEST_P(SSLClientSocketVersionTest, ConnectSignedCertTimestampsTLSExtension) {
   // Encoding of SCT List containing 'test'.
   base::StringPiece sct_ext("\x00\x06\x00\x04test", 8);
 
-  SpawnedTestServer::SSLOptions ssl_options;
-  ssl_options.signed_cert_timestamps_tls_ext = std::string(sct_ext);
-  ASSERT_TRUE(StartTestServer(ssl_options));
+  SSLServerConfig server_config = GetServerConfig();
+  server_config.signed_cert_timestamp_list =
+      std::vector<uint8_t>(sct_ext.begin(), sct_ext.end());
+  ASSERT_TRUE(
+      StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config));
 
   auto ct_verifier = std::make_unique<MockCTVerifier>();
 
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc
index b66c81f3..fefeef4 100644
--- a/net/socket/ssl_server_socket_impl.cc
+++ b/net/socket/ssl_server_socket_impl.cc
@@ -1056,6 +1056,12 @@
                               ssl_server_config_.ocsp_response.size());
   }
 
+  if (!ssl_server_config_.signed_cert_timestamp_list.empty()) {
+    SSL_CTX_set_signed_cert_timestamp_list(
+        ssl_ctx_.get(), ssl_server_config_.signed_cert_timestamp_list.data(),
+        ssl_server_config_.signed_cert_timestamp_list.size());
+  }
+
   if (ssl_server_config_.ech_keys) {
     CHECK(SSL_CTX_set1_ech_keys(ssl_ctx_.get(),
                                 ssl_server_config_.ech_keys.get()));
diff --git a/net/ssl/ssl_server_config.h b/net/ssl/ssl_server_config.h
index ed49857..ae5da3e 100644
--- a/net/ssl/ssl_server_config.h
+++ b/net/ssl/ssl_server_config.h
@@ -114,6 +114,10 @@
   // If non-empty, the DER-encoded OCSP response to staple.
   std::vector<uint8_t> ocsp_response;
 
+  // If non-empty, the serialized SignedCertificateTimestampList to send in the
+  // handshake.
+  std::vector<uint8_t> signed_cert_timestamp_list;
+
   // This is a workaround for BoringSSL's scopers not being copyable. See
   // https://crbug.com/boringssl/431.
   class NET_EXPORT ECHKeysContainer {
diff --git a/net/test/spawned_test_server/base_test_server.cc b/net/test/spawned_test_server/base_test_server.cc
index 71199ca..70937f8 100644
--- a/net/test/spawned_test_server/base_test_server.cc
+++ b/net/test/spawned_test_server/base_test_server.cc
@@ -474,13 +474,6 @@
     if (ssl_options_.tls_max_version != SSLOptions::TLS_MAX_VERSION_DEFAULT) {
       arguments->SetIntKey("tls-max-version", ssl_options_.tls_max_version);
     }
-    if (!ssl_options_.signed_cert_timestamps_tls_ext.empty()) {
-      std::string b64_scts_tls_ext;
-      base::Base64Encode(ssl_options_.signed_cert_timestamps_tls_ext,
-                         &b64_scts_tls_ext);
-      arguments->SetStringKey("signed-cert-timestamps-tls-ext",
-                              b64_scts_tls_ext);
-    }
     if (ssl_options_.alert_after_handshake)
       arguments->SetKey("alert-after-handshake", base::Value());
 
diff --git a/net/test/spawned_test_server/base_test_server.h b/net/test/spawned_test_server/base_test_server.h
index e16c548..367ba3b 100644
--- a/net/test/spawned_test_server/base_test_server.h
+++ b/net/test/spawned_test_server/base_test_server.h
@@ -147,14 +147,6 @@
     // The maximum TLS version to support.
     TLSMaxVersion tls_max_version = TLS_MAX_VERSION_DEFAULT;
 
-    // Temporary glue for testing: validation of SCTs is application-controlled
-    // and can be appropriately mocked out, so sending fake data here does not
-    // affect handshaking behaviour.
-    // TODO(ekasper): replace with valid SCT files for test certs.
-    // (Fake) SignedCertificateTimestampList (as a raw binary string) to send in
-    // a TLS extension.
-    std::string signed_cert_timestamps_tls_ext;
-
     // Whether to send a fatal alert immediately after completing the handshake.
     bool alert_after_handshake = false;
 
diff --git a/net/tools/testserver/testserver.py b/net/tools/testserver/testserver.py
index 10b7d54..2f8d643 100755
--- a/net/tools/testserver/testserver.py
+++ b/net/tools/testserver/testserver.py
@@ -102,9 +102,9 @@
 
   def __init__(self, server_address, request_hander_class, pem_cert_and_key,
                ssl_client_auth, ssl_client_cas, ssl_client_cert_types,
-               tls_intolerant, tls_intolerance_type, signed_cert_timestamps,
-               alert_after_handshake, simulate_tls13_downgrade,
-               simulate_tls12_downgrade, tls_max_version):
+               tls_intolerant, tls_intolerance_type, alert_after_handshake,
+               simulate_tls13_downgrade, simulate_tls12_downgrade,
+               tls_max_version):
     self.cert_chain = tlslite.api.X509CertChain()
     self.cert_chain.parsePemList(pem_cert_and_key)
     # Force using only python implementation - otherwise behavior is different
@@ -117,7 +117,6 @@
     self.ssl_client_auth = ssl_client_auth
     self.ssl_client_cas = []
     self.ssl_client_cert_types = []
-    self.signed_cert_timestamps = signed_cert_timestamps
 
     if ssl_client_auth:
       for ca_file in ssl_client_cas:
@@ -157,15 +156,13 @@
 
     try:
       self.tlsConnection = tlsConnection
-      tlsConnection.handshakeServer(
-          certChain=self.cert_chain,
-          privateKey=self.private_key,
-          sessionCache=self.session_cache,
-          reqCert=self.ssl_client_auth,
-          settings=self.ssl_handshake_settings,
-          reqCAs=self.ssl_client_cas,
-          reqCertTypes=self.ssl_client_cert_types,
-          signedCertTimestamps=self.signed_cert_timestamps)
+      tlsConnection.handshakeServer(certChain=self.cert_chain,
+                                    privateKey=self.private_key,
+                                    sessionCache=self.session_cache,
+                                    reqCert=self.ssl_client_auth,
+                                    settings=self.ssl_handshake_settings,
+                                    reqCAs=self.ssl_client_cas,
+                                    reqCertTypes=self.ssl_client_cert_types)
       tlsConnection.ignoreAbruptClose = True
       return True
     except tlslite.api.TLSAbruptCloseError:
@@ -417,7 +414,6 @@
             self.options.ssl_client_auth, self.options.ssl_client_ca,
             self.options.ssl_client_cert_type, self.options.tls_intolerant,
             self.options.tls_intolerance_type,
-            base64.b64decode(self.options.signed_cert_timestamps_tls_ext),
             self.options.alert_after_handshake,
             self.options.simulate_tls13_downgrade,
             self.options.simulate_tls12_downgrade, self.options.tls_max_version)
@@ -522,13 +518,6 @@
                                   help='Controls how the server reacts to a '
                                   'TLS version it is intolerant to. Valid '
                                   'values are "alert", "close", and "reset".')
-    self.option_parser.add_option('--signed-cert-timestamps-tls-ext',
-                                  dest='signed_cert_timestamps_tls_ext',
-                                  default='',
-                                  help='Base64 encoded SCT list. If set, '
-                                  'server will respond with a '
-                                  'signed_certificate_timestamp TLS extension '
-                                  'whenever the client supports it.')
     self.option_parser.add_option('--ssl-client-auth', action='store_true',
                                   help='Require SSL client auth on every '
                                   'connection.')
diff --git a/sql/database.cc b/sql/database.cc
index db90175..a91935a 100644
--- a/sql/database.cc
+++ b/sql/database.cc
@@ -34,6 +34,7 @@
 #include "base/threading/scoped_blocking_call.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/trace_event.h"
+#include "base/types/pass_key.h"
 #include "build/build_config.h"
 #include "sql/database_memory_dump_provider.h"
 #include "sql/initialization.h"
@@ -162,7 +163,7 @@
 namespace sql {
 
 // static
-Database::ErrorExpecterCallback* Database::current_expecter_cb_ = nullptr;
+Database::ScopedErrorExpecterCallback* Database::current_expecter_cb_ = nullptr;
 
 // static
 bool Database::IsExpectedSqliteError(int error) {
@@ -172,13 +173,16 @@
 }
 
 // static
-void Database::SetErrorExpecter(Database::ErrorExpecterCallback* cb) {
+void Database::SetScopedErrorExpecter(
+    Database::ScopedErrorExpecterCallback* cb,
+    base::PassKey<test::ScopedErrorExpecter>) {
   CHECK(!current_expecter_cb_);
   current_expecter_cb_ = cb;
 }
 
 // static
-void Database::ResetErrorExpecter() {
+void Database::ResetScopedErrorExpecter(
+    base::PassKey<test::ScopedErrorExpecter>) {
   CHECK(current_expecter_cb_);
   current_expecter_cb_ = nullptr;
 }
@@ -1764,10 +1768,12 @@
   }
 
   if (!error_callback_.is_null()) {
-    // Fire from a copy of the callback in case of reentry into
-    // re/set_error_callback().
-    // TODO(shess): <http://crbug.com/254584>
-    ErrorCallback(error_callback_).Run(sqlite_error_code, statement);
+    // Create an additional reference to the state in `error_callback_`, so the
+    // state doesn't go away if the callback changes `error_callback_` by
+    // calling set_error_callback() or reset_error_callback(). This avoids a
+    // subtle source of use-after-frees. See https://crbug.com/254584.
+    ErrorCallback error_callback_copy = error_callback_;
+    error_callback_copy.Run(sqlite_error_code, statement);
     return sqlite_error_code;
   }
 
diff --git a/sql/database.h b/sql/database.h
index ee10e7e..a38be0b4 100644
--- a/sql/database.h
+++ b/sql/database.h
@@ -23,6 +23,7 @@
 #include "base/sequence_checker.h"
 #include "base/strings/string_piece.h"
 #include "base/threading/scoped_blocking_call.h"
+#include "base/types/pass_key.h"
 #include "sql/internal_api_token.h"
 #include "sql/sql_features.h"
 #include "sql/statement_id.h"
@@ -215,8 +216,17 @@
   // Set an error-handling callback.  On errors, the error number (and
   // statement, if available) will be passed to the callback.
   //
-  // If no callback is set, the default action is to crash in debug
-  // mode or return failure in release mode.
+  // If no callback is set, the default error-handling behavior is invoked. The
+  // default behavior is to LOGs the error and propagate the failure.
+  //
+  // In DCHECK-enabled builds, the default error-handling behavior currently
+  // DCHECKs on errors. This is not correct, because DCHECKs are supposed to
+  // cover invariants and never fail, whereas SQLite errors can surface even on
+  // correct usage, due to I/O errors and data corruption. At some point in the
+  // future, errors will not result in DCHECKs.
+  //
+  // The callback will be called on the sequence used for database operations.
+  // The callback will never be called after the Database instance is destroyed.
   using ErrorCallback = base::RepeatingCallback<void(int, Statement*)>;
   void set_error_callback(const ErrorCallback& callback) {
     error_callback_ = callback;
@@ -562,10 +572,14 @@
   sqlite3* db(InternalApiToken) const { return db_; }
   bool poisoned(InternalApiToken) const { return poisoned_; }
 
- private:
-  // Allow test-support code to set/reset error expecter.
-  friend class test::ScopedErrorExpecter;
+  // Interface with sql::test::ScopedErrorExpecter.
+  using ScopedErrorExpecterCallback = base::RepeatingCallback<bool(int)>;
+  static void SetScopedErrorExpecter(ScopedErrorExpecterCallback* expecter,
+                                     base::PassKey<test::ScopedErrorExpecter>);
+  static void ResetScopedErrorExpecter(
+      base::PassKey<test::ScopedErrorExpecter>);
 
+ private:
   // Statement accesses StatementRef which we don't want to expose to everybody
   // (they should go through Statement).
   friend class Statement;
@@ -604,12 +618,8 @@
   // Internal helper for Does*Exist() functions.
   bool DoesSchemaItemExist(base::StringPiece name, base::StringPiece type);
 
-  // Accessors for global error-expecter, for injecting behavior during tests.
-  // See test/scoped_error_expecter.h.
-  using ErrorExpecterCallback = base::RepeatingCallback<bool(int)>;
-  static ErrorExpecterCallback* current_expecter_cb_;
-  static void SetErrorExpecter(ErrorExpecterCallback* expecter);
-  static void ResetErrorExpecter();
+  // Used to implement the interface with sql::test::ScopedErrorExpecter.
+  static ScopedErrorExpecterCallback* current_expecter_cb_;
 
   // A StatementRef is a refcounted wrapper around a sqlite statement pointer.
   // Refcounting allows us to give these statements out to sql::Statement
@@ -801,6 +811,15 @@
   // since memory was last released.
   int total_changes_at_last_release_ = 0;
 
+  // Called when a SQLite error occurs.
+  //
+  // This callback may be null, in which case errors are handled using a default
+  // behavior.
+  //
+  // This callback must never be exposed outside this Database instance. This is
+  // a straight-forward way to guarantee that this callback will not be called
+  // after the Database instance goes out of scope. set_error_callback() makes
+  // this guarantee.
   ErrorCallback error_callback_;
 
   // Developer-friendly database ID used in logging output and memory dumps.
diff --git a/sql/test/scoped_error_expecter.cc b/sql/test/scoped_error_expecter.cc
index 24a9145c..f605b7c 100644
--- a/sql/test/scoped_error_expecter.cc
+++ b/sql/test/scoped_error_expecter.cc
@@ -5,26 +5,23 @@
 #include "sql/test/scoped_error_expecter.h"
 
 #include "base/bind.h"
+#include "base/types/pass_key.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace sql {
 namespace test {
 
-// static
-int ScopedErrorExpecter::SQLiteLibVersionNumber() {
-  return sqlite3_libversion_number();
-}
-
 ScopedErrorExpecter::ScopedErrorExpecter()
     : checked_(false) {
   callback_ = base::BindRepeating(&ScopedErrorExpecter::ErrorSeen,
                                   base::Unretained(this));
-  Database::SetErrorExpecter(&callback_);
+  Database::SetScopedErrorExpecter(&callback_,
+                                   base::PassKey<ScopedErrorExpecter>());
 }
 
 ScopedErrorExpecter::~ScopedErrorExpecter() {
   EXPECT_TRUE(checked_) << " Test must call SawExpectedErrors()";
-  Database::ResetErrorExpecter();
+  Database::ResetScopedErrorExpecter(base::PassKey<ScopedErrorExpecter>());
 }
 
 void ScopedErrorExpecter::ExpectError(int err) {
diff --git a/sql/test/scoped_error_expecter.h b/sql/test/scoped_error_expecter.h
index a885a2c..f222f28d 100644
--- a/sql/test/scoped_error_expecter.h
+++ b/sql/test/scoped_error_expecter.h
@@ -7,6 +7,7 @@
 
 #include <set>
 
+#include "base/compiler_specific.h"
 #include "sql/database.h"
 
 // This is not strictly necessary for the operation of ScopedErrorExpecter, but
@@ -44,10 +45,6 @@
   // to call this results in an EXPECT failure when the instance is destructed.
   bool SawExpectedErrors() WARN_UNUSED_RESULT;
 
-  // Expose sqlite3_libversion_number() so that clients don't have to add a
-  // dependency on third_party/sqlite.
-  static int SQLiteLibVersionNumber() WARN_UNUSED_RESULT;
-
  private:
   // The target of the callback passed to Database::SetErrorExpecter().  If
   // |err| matches an error passed to ExpectError(), records |err| and returns
@@ -57,7 +54,7 @@
   bool ErrorSeen(int err);
 
   // Callback passed to Database::SetErrorExpecter().
-  Database::ErrorExpecterCallback callback_;
+  Database::ScopedErrorExpecterCallback callback_;
 
   // Record whether SawExpectedErrors() has been called.
   bool checked_;
diff --git a/sql/transaction.cc b/sql/transaction.cc
index 0bf18ec..bdbc093 100644
--- a/sql/transaction.cc
+++ b/sql/transaction.cc
@@ -10,35 +10,37 @@
 
 namespace sql {
 
-Transaction::Transaction(Database* database) : database_(database) {}
+Transaction::Transaction(Database* database) : database_(*database) {
+  DCHECK(database);
+}
 
 Transaction::~Transaction() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (is_open_)
-    database_->RollbackTransaction();
+  if (is_active_)
+    database_.RollbackTransaction();
 }
 
 bool Transaction::Begin() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!is_open_) << "Beginning a transaction twice!";
-  is_open_ = database_->BeginTransaction();
-  return is_open_;
+  DCHECK(!is_active_) << "Beginning a transaction twice!";
+  is_active_ = database_.BeginTransaction();
+  return is_active_;
 }
 
 void Transaction::Rollback() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(is_open_) << "Attempting to roll back a nonexistent transaction. "
-                   << "Did you remember to call Begin() and check its return?";
-  is_open_ = false;
-  database_->RollbackTransaction();
+  DCHECK(is_active_) << "Attempting to roll back a nonexistent transaction. "
+                     << "Did you call Begin() and check its return?";
+  is_active_ = false;
+  database_.RollbackTransaction();
 }
 
 bool Transaction::Commit() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(is_open_) << "Attempting to commit a nonexistent transaction. "
-                   << "Did you remember to call Begin() and check its return?";
-  is_open_ = false;
-  return database_->CommitTransaction();
+  DCHECK(is_active_) << "Attempting to commit a nonexistent transaction. "
+                     << "Did you call Begin() and check its return?";
+  is_active_ = false;
+  return database_.CommitTransaction();
 }
 
 }  // namespace sql
diff --git a/sql/transaction.h b/sql/transaction.h
index d092a97..16f6993 100644
--- a/sql/transaction.h
+++ b/sql/transaction.h
@@ -19,50 +19,78 @@
 // sequence.
 class COMPONENT_EXPORT(SQL) Transaction {
  public:
-  // Creates the scoped transaction object. You MUST call Begin() to begin the
-  // transaction. If you have begun a transaction and not committed it, the
-  // constructor will roll back the transaction. If you want to commit, you
-  // need to manually call Commit before this goes out of scope.
+  // Creates an inactive instance.
   //
-  // Nested transactions are supported. See sql::Database::BeginTransaction
-  // for details.
-  explicit Transaction(Database* connection);
+  // `database` must be non-null and must outlive the newly created instance.
+  //
+  // The instance must be activated by calling Begin().
+  //
+  // sql::Database implements "virtual" nested transactions, as documented in
+  // sql::Database::BeginTransaction(). This is a mis-feature, and should not be
+  // used in new code. The sql::Database implementation does not match the
+  // approach recommended at https://www.sqlite.org/lang_transaction.html.
+  explicit Transaction(Database* database);
   Transaction(const Transaction&) = delete;
   Transaction& operator=(const Transaction&) = delete;
   ~Transaction();
 
-  // Returns true when there is a transaction that has been successfully begun.
-  bool is_open() const {
-    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-    return is_open_;
-  }
-
-  // Begins the transaction. This uses the default sqlite "deferred" transaction
-  // type, which means that the DB lock is lazily acquired the next time the
-  // database is accessed, not in the begin transaction command.
+  // Activates an inactive transaction. Must be called after construction.
   //
-  // Returns false on failure. Note that if this fails, you shouldn't do
-  // anything you expect to be actually transactional, because it won't be!
+  // Returns false in case of failure. If this method fails, the database
+  // connection will still execute SQL statements, but they will not be enclosed
+  // in a transaction scope. In most cases, Begin() callers should handle
+  // failures by abandoning the high-level operation that was meant to be
+  // carried out in the transaction.
+  //
+  // In most cases (no nested transactions), this method issues a BEGIN
+  // statemnent, which invokes SQLite's deferred transaction startup documented
+  // in https://www.sqlite.org/lang_transaction.html. This means the database
+  // lock is not acquired by the time Begin() completes. Instead, the first
+  // statement after Begin() will attempt to acquire a read or write lock.
+  //
+  // This method is not idempotent. Calling Begin() twice on a Transaction will
+  // cause a DCHECK crash.
   bool Begin();
 
-  // Rolls back the transaction. This will happen automatically if you do
-  // nothing when the transaction goes out of scope.
+  // Explicitly rolls back the transaction. All changes will be forgotten.
+  //
+  // Most features can avoid calling this method, because Transactions that do
+  // not get Commit()ed are automatically rolled back when they go out of scope.
+  //
+  // This method is not idempotent. Calling Rollback() twice on a Transaction
+  // will cause a DCHECK crash.
+  //
+  // Must be called after a successful call to Begin(). Must not be called after
+  // Commit().
   void Rollback();
 
-  // Commits the transaction, returning true on success. This will return
-  // false if sqlite could not commit it, or if another transaction in the
-  // same outermost transaction has been rolled back (which necessitates a
-  // rollback of all transactions in that outermost one).
+  // Commits the transaction. All changes will be persisted in the database.
+  //
+  // Returns false in case of failure. The most failure case is a SQLite failure
+  // in committing the transaction. If sql::Database's support for nested
+  // transactions is in use, this method will also fail if any nested
+  // transaction has been rolled back.
+  //
+  // This method is not idempotent. Calling Commit() twice on a Transaction will
+  // cause a DCHECK crash.
+  //
+  // Must be called after a successful call to Begin(). Must not be called after
+  // Rollback().
   bool Commit();
 
+  // True if Begin() succeeded, and neither Commit() nor Rollback() were called.
+  bool IsActiveForTesting() const {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+    return is_active_;
+  }
+
  private:
   SEQUENCE_CHECKER(sequence_checker_);
 
-  Database* const database_;
+  Database& database_ GUARDED_BY_CONTEXT(sequence_checker_);
 
-  // True when the transaction is open, false when it's already been committed
-  // or rolled back.
-  bool is_open_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
+  // True between a successful Begin() and a Commit() / Rollback() call.
+  bool is_active_ GUARDED_BY_CONTEXT(sequence_checker_) = false;
 };
 
 }  // namespace sql
diff --git a/sql/transaction_unittest.cc b/sql/transaction_unittest.cc
index 48f75da2..2c89e3f0 100644
--- a/sql/transaction_unittest.cc
+++ b/sql/transaction_unittest.cc
@@ -42,14 +42,14 @@
 TEST_F(SQLTransactionTest, Commit) {
   {
     Transaction t(&db_);
-    EXPECT_FALSE(t.is_open());
+    EXPECT_FALSE(t.IsActiveForTesting());
     EXPECT_TRUE(t.Begin());
-    EXPECT_TRUE(t.is_open());
+    EXPECT_TRUE(t.IsActiveForTesting());
 
     EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
 
     t.Commit();
-    EXPECT_FALSE(t.is_open());
+    EXPECT_FALSE(t.IsActiveForTesting());
   }
 
   EXPECT_EQ(1, CountFoo());
@@ -60,9 +60,9 @@
   // scope.
   {
     Transaction t(&db_);
-    EXPECT_FALSE(t.is_open());
+    EXPECT_FALSE(t.IsActiveForTesting());
     EXPECT_TRUE(t.Begin());
-    EXPECT_TRUE(t.is_open());
+    EXPECT_TRUE(t.IsActiveForTesting());
 
     EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
   }
@@ -72,12 +72,12 @@
 
   // Test explicit rollback.
   Transaction t2(&db_);
-  EXPECT_FALSE(t2.is_open());
+  EXPECT_FALSE(t2.IsActiveForTesting());
   EXPECT_TRUE(t2.Begin());
 
   EXPECT_TRUE(db_.Execute("INSERT INTO foo (a, b) VALUES (1, 2)"));
   t2.Rollback();
-  EXPECT_FALSE(t2.is_open());
+  EXPECT_FALSE(t2.IsActiveForTesting());
 
   // Nothing should have been committed since it was explicitly rolled back.
   EXPECT_EQ(0, CountFoo());
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 804debb3..ac6e008 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -1318,7 +1318,7 @@
             ]
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 18
+          "shards": 20
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
       }
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 5d25154..c1e9ec5f 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -19993,7 +19993,7 @@
             ]
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 18
+          "shards": 20
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
       }
@@ -21268,7 +21268,7 @@
             ]
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 18
+          "shards": 20
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
       }
@@ -22538,7 +22538,7 @@
             ]
           },
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 18
+          "shards": 20
         },
         "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/"
       }
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json
index e76e5e3..230b972 100644
--- a/testing/buildbot/chromium.linux.json
+++ b/testing/buildbot/chromium.linux.json
@@ -891,7 +891,8 @@
   "Cast Linux": {
     "additional_compile_targets": [
       "cast_shell",
-      "cast_test_lists"
+      "cast_test_lists",
+      "core_runtime_simple"
     ],
     "gtest_tests": [
       {
@@ -1865,13 +1866,15 @@
   "Cast Linux ARM64": {
     "additional_compile_targets": [
       "cast_shell",
-      "cast_test_lists"
+      "cast_test_lists",
+      "core_runtime_simple"
     ]
   },
   "Cast Linux Debug": {
     "additional_compile_targets": [
       "cast_shell",
-      "cast_test_lists"
+      "cast_test_lists",
+      "core_runtime_simple"
     ]
   },
   "Fuchsia ARM64": {
diff --git a/testing/buildbot/chromium.perf.json b/testing/buildbot/chromium.perf.json
index 7018b94..df8f1a8 100644
--- a/testing/buildbot/chromium.perf.json
+++ b/testing/buildbot/chromium.perf.json
@@ -1706,13 +1706,12 @@
           "ignore_task_failure": false,
           "io_timeout": 21600,
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 2
+          "shards": 1
         },
         "trigger_script": {
           "args": [
             "--multiple-dimension-script-verbose",
-            "True",
-            "--use-dynamic-shards"
+            "True"
           ],
           "requires_simultaneous_shard_dispatch": true,
           "script": "//testing/trigger_scripts/perf_device_trigger.py"
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index 7e1efa4..48cf762 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -696,6 +696,10 @@
     "label": "//content/test:content_unittests",
     "type": "windowed_test_launcher",
   },
+  "core_runtime_simple": {
+    "label": "//chromecast/cast_core:core_runtime_simple",
+    "type": "additional_compile_target",
+  },
   "courgette_unittests": {
     "label": "//courgette:courgette_unittests",
     "type": "console_test_launcher",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index c2a08f89..927e94f 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -3883,7 +3883,7 @@
           'shards': 12,
         },
         'chromeos_swarming': {
-          'shards': 18,
+          'shards': 20,
         },
       },
     },
diff --git a/testing/buildbot/trybot_analyze_config.json b/testing/buildbot/trybot_analyze_config.json
index e5c6c9a7..00d5ad6 100644
--- a/testing/buildbot/trybot_analyze_config.json
+++ b/testing/buildbot/trybot_analyze_config.json
@@ -32,6 +32,11 @@
       "infra/recipes/.*"
     ]
   },
+  "chromeos": {
+    "exclusions": [
+      "chromeos/CHROMEOS_LKGM"
+    ]
+  },
   "chromium": {
     "exclusions": [
       "buildtools/checkdeps/.*",
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 72f4e32..72ab37b 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -4834,6 +4834,7 @@
         'additional_compile_targets': [
           'cast_shell',
           'cast_test_lists',
+          'core_runtime_simple',
         ],
         'test_suites': {
           'gtest_tests': 'chromium_linux_cast_video_gtests',
@@ -4846,6 +4847,7 @@
         'additional_compile_targets': [
           'cast_shell',
           'cast_test_lists',
+          'core_runtime_simple',
         ],
       },
       'Cast Linux Debug': {
@@ -4855,6 +4857,7 @@
         'additional_compile_targets': [
           'cast_shell',
           'cast_test_lists',
+          'core_runtime_simple',
         ],
       },
       'Fuchsia ARM64': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 362d7cea..4b6bdf2 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -651,21 +651,6 @@
             ]
         }
     ],
-    "AndroidThemeRefactor": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_20210714",
-                    "enable_features": [
-                        "ThemeRefactorAndroid"
-                    ]
-                }
-            ]
-        }
-    ],
     "AppListLaunchRecorder": [
         {
             "platforms": [
diff --git a/third_party/.gitignore b/third_party/.gitignore
index 091c737..e496483 100644
--- a/third_party/.gitignore
+++ b/third_party/.gitignore
@@ -54,6 +54,7 @@
 /byte_buddy/android_sdk_build_tools_25_0_2
 /byte_buddy/lib/
 /cardboard-java/src
+/cast_core/public/src
 /catapult
 /ced/src
 /checkstyle/*.jar
diff --git a/third_party/android_sdk/README.chromium b/third_party/android_sdk/README.chromium
index 5f531a51..61f23743 100644
--- a/third_party/android_sdk/README.chromium
+++ b/third_party/android_sdk/README.chromium
@@ -1,13 +1,14 @@
 Name: Android SDK
 URL: http://developer.android.com/sdk/index.html
 Version: 31
-  Android SDK Build-tools 31.0.0
-  Android SDK Command-line Tools 4.0
+  Android SDK Build-Tools 31.0.0
+  Android SDK Command-line Tools 5.0
   Android SDK Emulator 30.7.5
-  Android SDK Platform-tools 31.0.2
+  Android SDK Patch Applier v4
+  Android SDK Platform-Tools 31.0.3
   Android SDK Platform API 31
   Android SDK Sources 30
-  SDK Patch Applier v4
+  Google Cloud Messaging for Android Library, rev 3
 Security Critical: no
 License: Apache Version 2.0
 
@@ -27,8 +28,12 @@
   * Find the latest build on the android-sdk-packager builder. Get the CIPD
     instance id from its logs and update //DEPS:
     https://ci.chromium.org/p/chromium/builders/ci/android-sdk-packager
-  * Use `public/cmdline-tools/latest/bin/sdkmanager platform-tools` to make
-    sure that it is the latest version.
+  * Run `gclient sync` to fetch the updated files for the new instances in
+    //DEPS.
+  * Run `public/cmdline-tools/latest/bin/sdkmanager --list_installed` and make
+    sure that the packages are the new version.
+  * Run `cat public/cmdline-tools/latest/source.properties` to check the
+    version of cmdline-tools (this is not included in --list_installed).
   * Update this file with the new version.
 * Adding new sdk packages:
   * Prepare the CIPD yaml files for packages in the cipd/ directory.
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index ab6aa5b..3f9f8bb1 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1035,5 +1035,8 @@
     &kDelayLowPriorityRequestsAccordingToNetworkState,
     "CostReductionOfMultiplexedRequests", 0.5};
 
+const base::Feature kForceMajorVersion100InUserAgent{
+    "ForceMajorVersion100InUserAgent", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 4da6c0b..601a1bc 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -468,6 +468,12 @@
 BLINK_COMMON_EXPORT
 extern const base::FeatureParam<double> kCostReductionOfMultiplexedRequests;
 
+// If enabled, the major version number returned by Chrome will be forced to
+// 100.  This feature is only applicable for M96-M99 and will be removed after
+// M99.  The purpose of this feature is to allow users to test and proactively
+// fix any issues as we approach a 3-digit major version number.
+BLINK_COMMON_EXPORT extern const base::Feature kForceMajorVersion100InUserAgent;
+
 }  // namespace features
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
index b776667..5119af9b 100644
--- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
+++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.md
@@ -376,7 +376,7 @@
 
 Whether you should allow an interface to have a named constructor or not depends on the spec of each interface.
 
-### [NamedConstructor_CallWith] _(i)_
+### [NamedConstructor_CallWith=Document] _(i)_
 
 Summary: The same as `[CallWith]` but applied to the named constructors.
 
@@ -651,7 +651,7 @@
 
 For methods all calls are logged, and by default for attributes all access (calls to getter or setter) are logged, but this can be restricted to just read (getter) or just write (setter).
 
-### [CallWith] _(m, a)_, [GetterCallWith] _(a)_, [SetterCallWith] _(a)_, [ConstructorCallWith] _(i)_
+### [CallWith] _(m, a)_, [GetterCallWith] _(a)_, [SetterCallWith] _(a)
 
 Summary: `[CallWith]` indicates that the bindings code calls the Blink implementation with additional information.
 
@@ -757,37 +757,6 @@
 `[CallWith=...]` arguments are added at the _head_ of `XXX::Create(...)'s` arguments, and ` [RaisesException]`'s `ExceptionState` argument is added at the _tail_ of `XXX::Create(...)`'s arguments.
 ***
 
-#### [ConstructorCallWith] _(i)_
-
-Analogous to `[CallWith]`, but applied to interfaces with constructors, and takes different values.
-
-If `[Constructor]` is specified on an interface, `[ConstructorCallWith]` can be also specified to refine the arguments passed to the callback:
-
-```webidl
-[
-    Constructor(float x, float y, DOMString str),
-    ConstructorCallWith=ExecutionContext
-]
-interface XXX {
-    ...
-};
-```
-
-Then XXX::Create(...) can have the following signature
-
-```c++
-XXX* XXX::Create(ExecutionContext* context, float x, float y, const String& str) {
-  ...;
-}
-```
-
-Be careful when you use `[ConstructorCallWith=ScriptState]`.
-You should not store the passed-in ScriptState on a DOM object.
-This is because if the stored ScriptState is used by some method called by a different
-world (note that the DOM object is shared among multiple worlds), it leaks the ScriptState
-to the world. ScriptState must be carefully maintained in a way that doesn't leak
-to another world.
-
 ### [ContextEnabled] _(i)_
 
 Summary: `[ContextEnabled]` renders the generated interface bindings unavailable by default, but also generates code which allows individual script contexts opt into installing the bindings.
diff --git a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
index 77dda7d..36d940fc 100644
--- a/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
+++ b/third_party/blink/renderer/bindings/IDLExtendedAttributes.txt
@@ -42,9 +42,6 @@
 CheckSecurity=Receiver|ReturnValue
 Clamp
 Constructor
-# FIXME: remove [ConstructorCallWith=Document], as can instead use
-# [ConstructorCallWith=ExecutionContext] + toDocument(executionContext)
-ConstructorCallWith=ExecutionContext|ScriptState|Document
 ContextEnabled=*
 CrossOrigin=|Getter|Setter
 CrossOriginIsolated
diff --git a/third_party/blink/renderer/core/css/css_value_keywords.json5 b/third_party/blink/renderer/core/css/css_value_keywords.json5
index 0081309..cec24e372 100644
--- a/third_party/blink/renderer/core/css/css_value_keywords.json5
+++ b/third_party/blink/renderer/core/css/css_value_keywords.json5
@@ -1398,11 +1398,6 @@
     // https://drafts.csswg.org/css-conditional-4/#typedef-supports-selector-fn
     "selector",
 
-    // (screen-spanning) media feature
-    // none
-    "single-fold-vertical",
-    "single-fold-horizontal",
-
     // (device-posture) media feature
     "continuous",
     "folded",
diff --git a/third_party/blink/renderer/core/css/media_feature_names.json5 b/third_party/blink/renderer/core/css/media_feature_names.json5
index 4c70cb9..37075fd 100644
--- a/third_party/blink/renderer/core/css/media_feature_names.json5
+++ b/third_party/blink/renderer/core/css/media_feature_names.json5
@@ -62,6 +62,7 @@
     "-webkit-transform-3d",
     "scan",
     "device-posture",
-    "screen-spanning",
+    "horizontal-viewport-segments",
+    "vertical-viewport-segments",
   ],
 }
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc
index d1f712f..9527332 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -972,24 +972,32 @@
           value.id == CSSValueID::kBackButton);
 }
 
-static bool ScreenSpanningMediaFeatureEval(const MediaQueryExpValue& value,
-                                           MediaFeaturePrefix,
-                                           const MediaValues& media_values) {
-  ScreenSpanning screen_spanning_mode = media_values.GetScreenSpanning();
-
+static bool HorizontalViewportSegmentsMediaFeatureEval(
+    const MediaQueryExpValue& value,
+    MediaFeaturePrefix op,
+    const MediaValues& media_values) {
+  int horizontal_viewport_segments =
+      media_values.GetHorizontalViewportSegments();
   if (!value.IsValid())
-    return screen_spanning_mode != ScreenSpanning::kNone;
+    return true;
 
-  // We should not have parsed a valid MediaQueryExpValue if the value is not
-  // an identifier.
-  DCHECK(value.is_id);
+  float number;
+  return NumberValue(value, number) &&
+         CompareValue(horizontal_viewport_segments, static_cast<int>(number),
+                      op);
+}
 
-  return (screen_spanning_mode == ScreenSpanning::kNone &&
-          value.id == CSSValueID::kNone) ||
-         (screen_spanning_mode == ScreenSpanning::kSingleFoldVertical &&
-          value.id == CSSValueID::kSingleFoldVertical) ||
-         (screen_spanning_mode == ScreenSpanning::kSingleFoldHorizontal &&
-          value.id == CSSValueID::kSingleFoldHorizontal);
+static bool VerticalViewportSegmentsMediaFeatureEval(
+    const MediaQueryExpValue& value,
+    MediaFeaturePrefix op,
+    const MediaValues& media_values) {
+  int vertical_viewport_segments = media_values.GetVerticalViewportSegments();
+  if (!value.IsValid())
+    return true;
+
+  float number;
+  return NumberValue(value, number) &&
+         CompareValue(vertical_viewport_segments, static_cast<int>(number), op);
 }
 
 static bool DevicePostureMediaFeatureEval(const MediaQueryExpValue& value,
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
index 3b4c7dd..dbc7bab9 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator_test.cc
@@ -234,29 +234,40 @@
     {nullptr, false}  // Do not remove the terminator line.
 };
 
-MediaQueryEvaluatorTestCase g_screen_spanning_none_cases[] = {
-    {"(screen-spanning)", false},
-    {"(screen-spanning: single-fold-vertical)", false},
-    {"(screen-spanning: single-fold-horizontal)", false},
-    {"(screen-spanning: none)", true},
-    {"(screen-spanning: 1px)", false},
-    {"(screen-spanning: 16/9)", false},
+MediaQueryEvaluatorTestCase g_single_horizontal_viewport_segment_cases[] = {
+    {"(horizontal-viewport-segments)", true},
+    {"(horizontal-viewport-segments: 1)", true},
+    {"(horizontal-viewport-segments > 1)", false},
+    {"(horizontal-viewport-segments: 2)", false},
+    {"(horizontal-viewport-segments: none)", false},
+    {"(horizontal-viewport-segments: 1px)", false},
+    {"(horizontal-viewport-segments: 16/9)", false},
     {nullptr, false}  // Do not remove the terminator line.
 };
 
-MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_vertical_cases[] = {
-    {"(screen-spanning)", true},
-    {"(screen-spanning: single-fold-vertical)", true},
-    {"(screen-spanning: single-fold-horizontal)", false},
-    {"(screen-spanning: none)", false},
+MediaQueryEvaluatorTestCase g_double_horizontal_viewport_segment_cases[] = {
+    {"(horizontal-viewport-segments)", true},
+    {"(horizontal-viewport-segments: 1)", false},
+    {"(horizontal-viewport-segments: 2)", true},
+    {"(horizontal-viewport-segments: 3)", false},
     {nullptr, false}  // Do not remove the terminator line.
 };
 
-MediaQueryEvaluatorTestCase g_screen_spanning_single_fold_horizontal_cases[] = {
-    {"(screen-spanning)", true},
-    {"(screen-spanning: single-fold-vertical)", false},
-    {"(screen-spanning: single-fold-horizontal)", true},
-    {"(screen-spanning: none)", false},
+MediaQueryEvaluatorTestCase g_single_vertical_viewport_segment_cases[] = {
+    {"(vertical-viewport-segments)", true},
+    {"(vertical-viewport-segments: 1)", true},
+    {"(vertical-viewport-segments: 2)", false},
+    {"(vertical-viewport-segments: none)", false},
+    {"(vertical-viewport-segments: 1px)", false},
+    {"(vertical-viewport-segments: 16/9)", false},
+    {nullptr, false}  // Do not remove the terminator line.
+};
+
+MediaQueryEvaluatorTestCase g_double_vertical_viewport_segment_cases[] = {
+    {"(vertical-viewport-segments)", true},
+    {"(vertical-viewport-segments: 1)", false},
+    {"(vertical-viewport-segments: 2)", true},
+    {"(vertical-viewport-segments: 3)", false},
     {nullptr, false}  // Do not remove the terminator line.
 };
 
@@ -531,31 +542,41 @@
   }
 }
 
-TEST(MediaQueryEvaluatorTest, CachedScreenSpanning) {
+TEST(MediaQueryEvaluatorTest, CachedViewportSegments) {
   ScopedCSSFoldablesForTest scoped_feature(true);
 
   MediaValuesCached::MediaValuesCachedData data;
   {
-    data.screen_spanning = ScreenSpanning::kNone;
+    data.horizontal_viewport_segments = 1;
     MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
 
     MediaQueryEvaluator media_query_evaluator(*media_values);
-    TestMQEvaluator(g_screen_spanning_none_cases, media_query_evaluator);
-  }
-
-  {
-    data.screen_spanning = ScreenSpanning::kSingleFoldVertical;
-    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
-    MediaQueryEvaluator media_query_evaluator(*media_values);
-    TestMQEvaluator(g_screen_spanning_single_fold_vertical_cases,
+    TestMQEvaluator(g_single_horizontal_viewport_segment_cases,
                     media_query_evaluator);
   }
 
   {
-    data.screen_spanning = ScreenSpanning::kSingleFoldHorizontal;
+    data.horizontal_viewport_segments = 2;
     MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
     MediaQueryEvaluator media_query_evaluator(*media_values);
-    TestMQEvaluator(g_screen_spanning_single_fold_horizontal_cases,
+    TestMQEvaluator(g_double_horizontal_viewport_segment_cases,
+                    media_query_evaluator);
+  }
+
+  {
+    data.vertical_viewport_segments = 1;
+    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+
+    MediaQueryEvaluator media_query_evaluator(*media_values);
+    TestMQEvaluator(g_single_vertical_viewport_segment_cases,
+                    media_query_evaluator);
+  }
+
+  {
+    data.vertical_viewport_segments = 2;
+    MediaValues* media_values = MakeGarbageCollected<MediaValuesCached>(data);
+    MediaQueryEvaluator media_query_evaluator(*media_values);
+    TestMQEvaluator(g_double_vertical_viewport_segment_cases,
                     media_query_evaluator);
   }
 }
diff --git a/third_party/blink/renderer/core/css/media_query_exp.cc b/third_party/blink/renderer/core/css/media_query_exp.cc
index 0f47524e..ccccd156 100644
--- a/third_party/blink/renderer/core/css/media_query_exp.cc
+++ b/third_party/blink/renderer/core/css/media_query_exp.cc
@@ -112,14 +112,6 @@
     }
   }
 
-  if (RuntimeEnabledFeatures::CSSFoldablesEnabled()) {
-    if (media_feature == media_feature_names::kScreenSpanningMediaFeature) {
-      return ident == CSSValueID::kNone ||
-             ident == CSSValueID::kSingleFoldVertical ||
-             ident == CSSValueID::kSingleFoldHorizontal;
-    }
-  }
-
   if (RuntimeEnabledFeatures::DevicePostureEnabled()) {
     if (media_feature == media_feature_names::kDevicePostureMediaFeature) {
       return ident == CSSValueID::kContinuous || ident == CSSValueID::kFolded ||
@@ -163,16 +155,29 @@
 
 static inline bool FeatureExpectingPositiveInteger(
     const String& media_feature) {
-  return media_feature == media_feature_names::kColorMediaFeature ||
-         media_feature == media_feature_names::kMaxColorMediaFeature ||
-         media_feature == media_feature_names::kMinColorMediaFeature ||
-         media_feature == media_feature_names::kColorIndexMediaFeature ||
-         media_feature == media_feature_names::kMaxColorIndexMediaFeature ||
-         media_feature == media_feature_names::kMinColorIndexMediaFeature ||
-         media_feature == media_feature_names::kMonochromeMediaFeature ||
-         media_feature == media_feature_names::kMaxMonochromeMediaFeature ||
-         media_feature == media_feature_names::kMinMonochromeMediaFeature ||
-         media_feature == media_feature_names::kImmersiveMediaFeature;
+  if (media_feature == media_feature_names::kColorMediaFeature ||
+      media_feature == media_feature_names::kMaxColorMediaFeature ||
+      media_feature == media_feature_names::kMinColorMediaFeature ||
+      media_feature == media_feature_names::kColorIndexMediaFeature ||
+      media_feature == media_feature_names::kMaxColorIndexMediaFeature ||
+      media_feature == media_feature_names::kMinColorIndexMediaFeature ||
+      media_feature == media_feature_names::kMonochromeMediaFeature ||
+      media_feature == media_feature_names::kMaxMonochromeMediaFeature ||
+      media_feature == media_feature_names::kMinMonochromeMediaFeature ||
+      media_feature == media_feature_names::kImmersiveMediaFeature) {
+    return true;
+  }
+
+  if (RuntimeEnabledFeatures::CSSFoldablesEnabled()) {
+    if (media_feature ==
+            media_feature_names::kHorizontalViewportSegmentsMediaFeature ||
+        media_feature ==
+            media_feature_names::kVerticalViewportSegmentsMediaFeature) {
+      return true;
+    }
+  }
+
+  return false;
 }
 
 static inline bool FeatureWithPositiveInteger(const String& media_feature,
@@ -254,7 +259,11 @@
          (media_feature == media_feature_names::kOriginTrialTestMediaFeature &&
           RuntimeEnabledFeatures::OriginTrialsSampleAPIEnabled(
               execution_context)) ||
-         (media_feature == media_feature_names::kScreenSpanningMediaFeature &&
+         (media_feature ==
+              media_feature_names::kHorizontalViewportSegmentsMediaFeature &&
+          RuntimeEnabledFeatures::CSSFoldablesEnabled()) ||
+         (media_feature ==
+              media_feature_names::kVerticalViewportSegmentsMediaFeature &&
           RuntimeEnabledFeatures::CSSFoldablesEnabled()) ||
          (media_feature == media_feature_names::kDevicePostureMediaFeature &&
           RuntimeEnabledFeatures::DevicePostureEnabled());
diff --git a/third_party/blink/renderer/core/css/media_query_set_test.cc b/third_party/blink/renderer/core/css/media_query_set_test.cc
index c7650b7..04acbc19b 100644
--- a/third_party/blink/renderer/core/css/media_query_set_test.cc
+++ b/third_party/blink/renderer/core/css/media_query_set_test.cc
@@ -200,12 +200,14 @@
   MediaQuerySetTestCase test_cases[] = {
       {"(forced-colors)", "not all"},
       {"(navigation-controls)", "not all"},
-      {"(screen-spanning)", "not all"},
+      {"(horizontal-viewport-segments)", "not all"},
+      {"(vertical-viewport-segments)", "not all"},
       {"(device-posture)", "not all"},
       {"(shape: rect)", "not all"},
       {"(forced-colors: none)", "not all"},
       {"(navigation-controls: none)", "not all"},
-      {"(screen-spanning:none)", "not all"},
+      {"(horizontal-viewport-segments: 1)", "not all"},
+      {"(vertical-viewport-segments: 1)", "not all"},
       {"(device-posture:none)", "not all"},
       {nullptr, nullptr}  // Do not remove the terminator line.
   };
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc
index 4117ba3..9edddc0 100644
--- a/third_party/blink/renderer/core/css/media_values.cc
+++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -305,27 +305,34 @@
   return frame->GetSettings()->GetNavigationControls();
 }
 
-ScreenSpanning MediaValues::CalculateScreenSpanning(LocalFrame* frame) {
+int MediaValues::CalculateHorizontalViewportSegments(LocalFrame* frame) {
   if (!frame->GetWidgetForLocalRoot())
-    return ScreenSpanning::kNone;
+    return 1;
 
   WebVector<gfx::Rect> window_segments =
       frame->GetWidgetForLocalRoot()->WindowSegments();
-
-  if (window_segments.size() == 2) {
-    // If there are two segments and the y value of the segments is the same,
-    // we have side-by-side segments which are represented as a single vertical
-    // fold.
-    if (window_segments[0].y() == window_segments[1].y())
-      return ScreenSpanning::kSingleFoldVertical;
-
-    // If the x value of the segments is the same, we have stacked segments
-    // which are represented as a single horizontal fold.
-    if (window_segments[0].x() == window_segments[1].x())
-      return ScreenSpanning::kSingleFoldHorizontal;
+  WTF::HashSet<int> unique_x;
+  for (const auto& segment : window_segments) {
+    // HashSet can't have 0 as a key, so add 1 to all the values we see.
+    unique_x.insert(segment.x() + 1);
   }
 
-  return ScreenSpanning::kNone;
+  return static_cast<int>(unique_x.size());
+}
+
+int MediaValues::CalculateVerticalViewportSegments(LocalFrame* frame) {
+  if (!frame->GetWidgetForLocalRoot())
+    return 1;
+
+  WebVector<gfx::Rect> window_segments =
+      frame->GetWidgetForLocalRoot()->WindowSegments();
+  WTF::HashSet<int> unique_y;
+  for (const auto& segment : window_segments) {
+    // HashSet can't have 0 as a key, so add 1 to all the values we see.
+    unique_y.insert(segment.y() + 1);
+  }
+
+  return static_cast<int>(unique_y.size());
 }
 
 device::mojom::blink::DevicePostureType MediaValues::CalculateDevicePosture(
diff --git a/third_party/blink/renderer/core/css/media_values.h b/third_party/blink/renderer/core/css/media_values.h
index 95b2484..7ee788ec 100644
--- a/third_party/blink/renderer/core/css/media_values.h
+++ b/third_party/blink/renderer/core/css/media_values.h
@@ -24,7 +24,6 @@
 enum class ColorSpaceGamut;
 enum class ForcedColors;
 enum class NavigationControls;
-enum class ScreenSpanning { kNone, kSingleFoldHorizontal, kSingleFoldVertical };
 
 mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme(
     CSSValueID id);
@@ -93,7 +92,8 @@
   virtual bool PrefersReducedData() const = 0;
   virtual ForcedColors GetForcedColors() const = 0;
   virtual NavigationControls GetNavigationControls() const = 0;
-  virtual ScreenSpanning GetScreenSpanning() const = 0;
+  virtual int GetHorizontalViewportSegments() const = 0;
+  virtual int GetVerticalViewportSegments() const = 0;
   virtual device::mojom::blink::DevicePostureType GetDevicePosture() const = 0;
 
  protected:
@@ -124,7 +124,8 @@
   static bool CalculatePrefersReducedData(LocalFrame*);
   static ForcedColors CalculateForcedColors(LocalFrame*);
   static NavigationControls CalculateNavigationControls(LocalFrame*);
-  static ScreenSpanning CalculateScreenSpanning(LocalFrame*);
+  static int CalculateHorizontalViewportSegments(LocalFrame*);
+  static int CalculateVerticalViewportSegments(LocalFrame*);
   static device::mojom::blink::DevicePostureType CalculateDevicePosture(
       LocalFrame*);
 };
diff --git a/third_party/blink/renderer/core/css/media_values_cached.cc b/third_party/blink/renderer/core/css/media_values_cached.cc
index 935072d..b05fd0e 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.cc
+++ b/third_party/blink/renderer/core/css/media_values_cached.cc
@@ -54,7 +54,10 @@
     prefers_reduced_data = MediaValues::CalculatePrefersReducedData(frame);
     forced_colors = MediaValues::CalculateForcedColors(frame);
     navigation_controls = MediaValues::CalculateNavigationControls(frame);
-    screen_spanning = MediaValues::CalculateScreenSpanning(frame);
+    horizontal_viewport_segments =
+        MediaValues::CalculateHorizontalViewportSegments(frame);
+    vertical_viewport_segments =
+        MediaValues::CalculateVerticalViewportSegments(frame);
     device_posture = MediaValues::CalculateDevicePosture(frame);
   }
 }
@@ -196,8 +199,12 @@
   return data_.navigation_controls;
 }
 
-ScreenSpanning MediaValuesCached::GetScreenSpanning() const {
-  return data_.screen_spanning;
+int MediaValuesCached::GetHorizontalViewportSegments() const {
+  return data_.horizontal_viewport_segments;
+}
+
+int MediaValuesCached::GetVerticalViewportSegments() const {
+  return data_.vertical_viewport_segments;
 }
 
 device::mojom::blink::DevicePostureType MediaValuesCached::GetDevicePosture()
diff --git a/third_party/blink/renderer/core/css/media_values_cached.h b/third_party/blink/renderer/core/css/media_values_cached.h
index d9ec747c..9b76d2e 100644
--- a/third_party/blink/renderer/core/css/media_values_cached.h
+++ b/third_party/blink/renderer/core/css/media_values_cached.h
@@ -59,7 +59,8 @@
     bool prefers_reduced_data = false;
     ForcedColors forced_colors = ForcedColors::kNone;
     NavigationControls navigation_controls = NavigationControls::kNone;
-    ScreenSpanning screen_spanning = ScreenSpanning::kNone;
+    int horizontal_viewport_segments = 0;
+    int vertical_viewport_segments = 0;
     device::mojom::blink::DevicePostureType device_posture =
         device::mojom::blink::DevicePostureType::kContinuous;
 
@@ -93,7 +94,8 @@
       data.prefers_reduced_data = prefers_reduced_data;
       data.forced_colors = forced_colors;
       data.navigation_controls = navigation_controls;
-      data.screen_spanning = screen_spanning;
+      data.horizontal_viewport_segments = horizontal_viewport_segments;
+      data.vertical_viewport_segments = vertical_viewport_segments;
       data.device_posture = device_posture;
       return data;
     }
@@ -137,7 +139,8 @@
   bool PrefersReducedData() const override;
   ForcedColors GetForcedColors() const override;
   NavigationControls GetNavigationControls() const override;
-  ScreenSpanning GetScreenSpanning() const override;
+  int GetHorizontalViewportSegments() const override;
+  int GetVerticalViewportSegments() const override;
   device::mojom::blink::DevicePostureType GetDevicePosture() const override;
 
   void OverrideViewportDimensions(double width, double height) override;
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.cc b/third_party/blink/renderer/core/css/media_values_dynamic.cc
index 99b20c7..ca82be6 100644
--- a/third_party/blink/renderer/core/css/media_values_dynamic.cc
+++ b/third_party/blink/renderer/core/css/media_values_dynamic.cc
@@ -169,8 +169,12 @@
   return CalculateNavigationControls(frame_);
 }
 
-ScreenSpanning MediaValuesDynamic::GetScreenSpanning() const {
-  return CalculateScreenSpanning(frame_);
+int MediaValuesDynamic::GetHorizontalViewportSegments() const {
+  return CalculateHorizontalViewportSegments(frame_);
+}
+
+int MediaValuesDynamic::GetVerticalViewportSegments() const {
+  return CalculateVerticalViewportSegments(frame_);
 }
 
 device::mojom::blink::DevicePostureType MediaValuesDynamic::GetDevicePosture()
diff --git a/third_party/blink/renderer/core/css/media_values_dynamic.h b/third_party/blink/renderer/core/css/media_values_dynamic.h
index 3f6a4da..3ac6941 100644
--- a/third_party/blink/renderer/core/css/media_values_dynamic.h
+++ b/third_party/blink/renderer/core/css/media_values_dynamic.h
@@ -54,7 +54,8 @@
   bool PrefersReducedData() const override;
   ForcedColors GetForcedColors() const override;
   NavigationControls GetNavigationControls() const override;
-  ScreenSpanning GetScreenSpanning() const override;
+  int GetHorizontalViewportSegments() const override;
+  int GetVerticalViewportSegments() const override;
   device::mojom::blink::DevicePostureType GetDevicePosture() const override;
   Document* GetDocument() const override;
   bool HasValues() const override;
diff --git a/third_party/blink/renderer/core/css/style_rule.h b/third_party/blink/renderer/core/css/style_rule.h
index b46b69e..639ebd7 100644
--- a/third_party/blink/renderer/core/css/style_rule.h
+++ b/third_party/blink/renderer/core/css/style_rule.h
@@ -464,7 +464,7 @@
 struct DowncastTraits<StyleRuleGroup> {
   static bool AllowFrom(const StyleRuleBase& rule) {
     return rule.IsMediaRule() || rule.IsSupportsRule() ||
-           rule.IsContainerRule();
+           rule.IsContainerRule() || rule.IsLayerBlockRule();
   }
 };
 
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index ff99127d..e76cca4 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -418,7 +418,9 @@
     // on). Inline display types end up on a line, and are therefore monolithic,
     // so we can allow those.
     if (!style.IsDisplayInlineType()) {
-      if (style.IsDisplayTableType() || style.IsDisplayGridBox() ||
+      if (style.IsDisplayTableType() ||
+          (style.IsDisplayGridBox() &&
+           !RuntimeEnabledFeatures::LayoutNGGridFragmentationEnabled()) ||
           ((style.IsDisplayFlexibleBox() ||
             style.IsDeprecatedFlexboxUsingFlexLayout()) &&
            !RuntimeEnabledFeatures::LayoutNGFlexFragmentationEnabled())) {
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index be646cf..12158fd 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1287,8 +1287,8 @@
   DCHECK(IsLocalRoot());
 
   // A change in the window segments requires re-evaluation of media queries
-  // for the local frame subtree (the segments affect the "screen-spanning"
-  // feature).
+  // for the local frame subtree (the segments affect the
+  // "horizontal-viewport-segments" and "vertical-viewport-segments" features).
   MediaQueryAffectingValueChangedForLocalSubtree(MediaValueChange::kOther);
 
   // Also need to update the environment variables related to window segments.
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.idl b/third_party/blink/renderer/core/html/forms/html_option_element.idl
index a243648..d0a475f 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.idl
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.idl
@@ -21,7 +21,6 @@
 // https://html.spec.whatwg.org/C/#the-option-element
 
 [
-    ConstructorCallWith=Document,
     Exposed=Window,
     HTMLConstructor,
     NamedConstructor=Option(optional DOMString data = "",
diff --git a/third_party/blink/renderer/core/html/html_image_element.idl b/third_party/blink/renderer/core/html/html_image_element.idl
index bcd431f..b4fef4d04 100644
--- a/third_party/blink/renderer/core/html/html_image_element.idl
+++ b/third_party/blink/renderer/core/html/html_image_element.idl
@@ -22,7 +22,6 @@
 
 [
     ActiveScriptWrappable,
-    ConstructorCallWith=Document,
     Exposed=Window,
     HTMLConstructor,
     NamedConstructor=Image(optional unsigned long width, optional unsigned long height),
diff --git a/third_party/blink/renderer/core/html/media/html_audio_element.idl b/third_party/blink/renderer/core/html/media/html_audio_element.idl
index 3c84dc9d..08bf2cb 100644
--- a/third_party/blink/renderer/core/html/media/html_audio_element.idl
+++ b/third_party/blink/renderer/core/html/media/html_audio_element.idl
@@ -26,7 +26,6 @@
 // https://html.spec.whatwg.org/C/#the-audio-element
 
 [
-    ConstructorCallWith=Document,
     Exposed=Window,
     HTMLConstructor,
     NamedConstructor=Audio(optional DOMString src),
diff --git a/third_party/blink/renderer/core/script/modulator_impl_base.cc b/third_party/blink/renderer/core/script/modulator_impl_base.cc
index 96d6739..157ff5b 100644
--- a/third_party/blink/renderer/core/script/modulator_impl_base.cc
+++ b/third_party/blink/renderer/core/script/modulator_impl_base.cc
@@ -209,23 +209,26 @@
     const ModuleRequest& module_request) const {
   String module_type_string = module_request.GetModuleTypeString();
   if (module_type_string.IsNull()) {
-    // Per https://github.com/whatwg/html/pull/5883, if no type assertion is
-    // provided then the import should be treated as a JavaScript module.
+    // <spec href="https://html.spec.whatwg.org/#fetch-a-single-module-script"
+    // step="1">Let module type be "javascript".</spec> If no type assertion is
+    // provided, the import is treated as a JavaScript module.
     return ModuleType::kJavaScript;
   } else if (base::FeatureList::IsEnabled(blink::features::kJSONModules) &&
              module_type_string == "json") {
-    // Per https://github.com/whatwg/html/pull/5658, a "json" type assertion
-    // indicates that the import should be treated as a JSON module script.
+    // <spec href="https://html.spec.whatwg.org/#fetch-a-single-module-script"
+    // step="17"> If...module type is "json", then set module script to the
+    // result of creating a JSON module script...</spec>
     return ModuleType::kJSON;
   } else if (RuntimeEnabledFeatures::CSSModulesEnabled() &&
-             module_type_string == "css") {
-    // Per https://github.com/whatwg/html/pull/4898, a "css" type assertion
-    // indicates that the import should be treated as a CSS module script.
+             module_type_string == "css" && GetExecutionContext()->IsWindow()) {
+    // <spec href="https://html.spec.whatwg.org/#fetch-a-single-module-script"
+    // step="16"> If...module type is "css", then set module script to the
+    // result of creating a CSS module script...</spec>
     return ModuleType::kCSS;
   } else {
-    // Per https://github.com/whatwg/html/pull/5883, if an unsupported type
-    // assertion is provided then the import should be treated as an error
-    // similar to an invalid module specifier.
+    // Per https://github.com/whatwg/html/pull/7066, unrecognized type
+    // assertions or "css" type assertions in a non-document context should be
+    // treated as an error similar to an invalid module specifier.
     return ModuleType::kInvalid;
   }
 }
diff --git a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
index 80d602d7..9c5bff44 100644
--- a/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
+++ b/third_party/blink/renderer/core/script/value_wrapper_synthetic_module_script.cc
@@ -39,13 +39,8 @@
   ExecutionContext* execution_context = ExecutionContext::From(script_state);
   UseCounter::Count(execution_context, WebFeature::kCreateCSSModuleScript);
   auto* context_window = DynamicTo<LocalDOMWindow>(execution_context);
-  if (!context_window) {
-    v8::Local<v8::Value> error = V8ThrowException::CreateTypeError(
-        isolate, "Cannot create CSS Module in non-document context");
-    return ValueWrapperSyntheticModuleScript::CreateWithError(
-        v8::Local<v8::Value>(), settings_object, params.SourceURL(), KURL(),
-        ScriptFetchOptions(), error);
-  }
+  DCHECK(context_window)
+      << "Attempted to create a CSS Module in non-document context";
   CSSStyleSheetInit* init = CSSStyleSheetInit::Create();
   // The base URL used to construct the CSSStyleSheet is also used for
   // DevTools as the CSS source URL. This is fine since these two values
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn
index 6d88713..256bec313 100644
--- a/third_party/blink/renderer/modules/BUILD.gn
+++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -561,6 +561,7 @@
     "push_messaging/push_message_data_test.cc",
     "push_messaging/push_subscription_test.cc",
     "remoteplayback/remote_playback_test.cc",
+    "scheduler/dom_scheduler_test.cc",
     "screen_orientation/screen_orientation_controller_test.cc",
     "sensor/ambient_light_sensor_test.cc",
     "sensor/sensor_test_utils.cc",
diff --git a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.cc b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.cc
index c74b55f..083d513 100644
--- a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.cc
@@ -42,12 +42,12 @@
     return;
   }
 
-  if (called_) {
-    exception_state.ThrowDOMException(DOMExceptionCode::kNotSupportedError,
+  if (focus_called_) {
+    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                       "Method may only be called once.");
     return;
   }
-  called_ = true;
+  focus_called_ = true;
 
   client->FocusCapturedSurface(
       descriptor_id_,
diff --git a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.h b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.h
index 4fdd781..55539a5 100644
--- a/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.h
+++ b/third_party/blink/renderer/modules/mediastream/focusable_media_stream_track.h
@@ -34,7 +34,7 @@
 
 #if !defined(OS_ANDROID)
   // First call to focus() is allowed. Subsequent calls produce an error.
-  bool called_ = false;
+  bool focus_called_ = false;
 #endif
 };
 
diff --git a/third_party/blink/renderer/modules/payments/payment_manager.idl b/third_party/blink/renderer/modules/payments/payment_manager.idl
index 54e4fe7..bfee8f8 100644
--- a/third_party/blink/renderer/modules/payments/payment_manager.idl
+++ b/third_party/blink/renderer/modules/payments/payment_manager.idl
@@ -13,8 +13,7 @@
 
 [
     Exposed=Window,
-    RuntimeEnabled=PaymentApp,
-    ConstructorCallWith=ExecutionContext
+    RuntimeEnabled=PaymentApp
 ] interface PaymentManager {
     [SameObject] readonly attribute PaymentInstruments instruments;
     attribute DOMString userHint;
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler.h b/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
index 1acdcb25..47cc9ac2 100644
--- a/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler.h
@@ -22,6 +22,7 @@
 class DOMTaskSignal;
 class ExceptionState;
 class SchedulerPostTaskOptions;
+class DOMSchedulerTest;
 class V8SchedulerPostTaskCallback;
 class WebSchedulingTaskQueue;
 
@@ -90,6 +91,8 @@
   void Trace(Visitor*) const override;
 
  private:
+  friend class DOMSchedulerTest;
+
   static constexpr size_t kWebSchedulingPriorityCount =
       static_cast<size_t>(WebSchedulingPriority::kLastPriority) + 1;
 
diff --git a/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc b/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc
new file mode 100644
index 0000000..eb50daf
--- /dev/null
+++ b/third_party/blink/renderer/modules/scheduler/dom_scheduler_test.cc
@@ -0,0 +1,180 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/scheduler/dom_scheduler.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/script/classic_script.h"
+#include "third_party/blink/renderer/core/testing/page_test_base.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h"
+
+namespace blink {
+
+class DOMSchedulerTest : public PageTestBase {
+ public:
+  void SetUp() override {
+    EnablePlatform();
+    PageTestBase::SetUp();
+    GetFrame().GetSettings()->SetScriptEnabled(true);
+
+    ExecutionContext* context = GetFrame().DomWindow();
+    scheduler_ = WrapPersistent(DOMScheduler::scheduler(*context));
+  }
+
+  void ExecuteScript(const char* script) {
+    ClassicScript::CreateUnspecifiedScript(ScriptSourceCode(script))
+        ->RunScript(GetFrame().DomWindow());
+  }
+
+  wtf_size_t GetTrackedSignalCount() const {
+    return scheduler_->signal_to_task_queue_map_.size();
+  }
+
+  wtf_size_t GetDynamicPriorityTaskQueueCount() const {
+    wtf_size_t count = 0;
+    for (const auto& it : scheduler_->signal_to_task_queue_map_) {
+      if (!scheduler_->fixed_priority_task_queues_.Contains(it.value)) {
+        ++count;
+      }
+    }
+    return count;
+  }
+
+ private:
+  Persistent<DOMScheduler> scheduler_;
+};
+
+TEST_F(DOMSchedulerTest, ImplicitTaskSignalCreation) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  const char* kScript =
+      "scheduler.postTask(() => {}, {priority: 'user-blocking'});"
+      "scheduler.postTask(() => {}, {priority: 'user-blocking'});"
+      "scheduler.postTask(() => {}, {priority: 'user-visible'});"
+      "scheduler.postTask(() => {}, {priority: 'user-visible'});"
+      "scheduler.postTask(() => {}, {priority: 'background'});"
+      "scheduler.postTask(() => {}, {priority: 'background'});";
+  ExecuteScript(kScript);
+
+  // We create and track a new implicit TaskSignal each time we see a fixed
+  // priority, but they should map to existing, fixed-priority task queues.
+  EXPECT_EQ(GetTrackedSignalCount(), 6u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+}
+
+TEST_F(DOMSchedulerTest, ImplicitTaskSignalReused) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  const char* kScript =
+      "const signal = scheduler.currentTaskSignal;"
+      "scheduler.postTask(() => {}, {signal});"
+      "scheduler.postTask(() => {}, {signal});"
+      "scheduler.postTask(() => {}, {signal});";
+  ExecuteScript(kScript);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+}
+
+TEST_F(DOMSchedulerTest, ImplicitTaskSignalWithAbortSignal) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  const char* kScript1 =
+      "const controller = new AbortController();"
+      "const signal = controller.signal;"
+      "scheduler.postTask(() => {}, {signal});";
+  ExecuteScript(kScript1);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  // This causes another implicit signal to be created.
+  const char* kScript2 = "scheduler.postTask(() => {}, {signal});";
+  ExecuteScript(kScript2);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 2u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+}
+
+TEST_F(DOMSchedulerTest, DynamicPriorityTaskQueueCreation) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  const char* kScript1 =
+      "const controller1 = new TaskController();"
+      "const signal1 = controller1.signal;"
+      "scheduler.postTask(() => {}, {signal: signal1});";
+  ExecuteScript(kScript1);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 1u);
+
+  const char* kScript2 =
+      "const controller2 = new TaskController();"
+      "const signal2 = controller2.signal;"
+      "scheduler.postTask(() => {}, {signal: signal2});";
+  ExecuteScript(kScript2);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 2u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 2u);
+}
+
+TEST_F(DOMSchedulerTest, DynamicPriorityTaskQueueCreationReuseSignal) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+
+  const char* kScript =
+      "const controller = new TaskController();"
+      "const signal = controller.signal;"
+      "scheduler.postTask(() => {}, {signal});"
+      "scheduler.postTask(() => {}, {signal});"
+      "scheduler.postTask(() => {}, {signal});";
+  ExecuteScript(kScript);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 1u);
+}
+
+TEST_F(DOMSchedulerTest, DynamicPriorityTaskQueueGarbageCollection) {
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+
+  // Schedule a task but let the associated signal go out of scope. The dynamic
+  // priority task queue should stay alive until after the task runs.
+  const char* kScript =
+      "function test() {"
+      "  const controller = new TaskController();"
+      "  const signal = controller.signal;"
+      "  scheduler.postTask(() => {}, {signal});"
+      "}"
+      "test();";
+  ExecuteScript(kScript);
+
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 1u);
+
+  // The signal and controller are out of scope in JS, but the task queue
+  // should remain alive and tracked since the task hasn't run yet.
+  ThreadState::Current()->CollectAllGarbageForTesting();
+  EXPECT_EQ(GetTrackedSignalCount(), 1u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 1u);
+
+  // Running the scheduled task and running garbage collection should now cause
+  // the siganl to be untracked and the task queue to be destroyed.
+  platform()->RunUntilIdle();
+  ThreadState::Current()->CollectAllGarbageForTesting();
+  EXPECT_EQ(GetTrackedSignalCount(), 0u);
+  EXPECT_EQ(GetDynamicPriorityTaskQueueCount(), 0u);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc b/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
index 1657720..c98cbe12 100644
--- a/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/audio_scheduled_source_node.cc
@@ -262,11 +262,13 @@
   // let DispatchEvent take are of sending the event to the right
   // place,
   DCHECK(IsMainThread());
-  if (!Context() || !Context()->GetExecutionContext())
-    return;
-  if (GetNode())
-    GetNode()->DispatchEvent(*Event::Create(event_type_names::kEnded));
 
+  if (GetNode()) {
+    DispatchEventResult result =
+        GetNode()->DispatchEvent(*Event::Create(event_type_names::kEnded));
+    if (result == DispatchEventResult::kCanceledBeforeDispatch)
+      return;
+  }
   on_ended_notification_pending_ = false;
 }
 
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
index 57f4a3dd..449c73c 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
@@ -84,6 +84,7 @@
   }
 
   dawn_desc.depthStoreOp = AsDawnEnum<WGPUStoreOp>(webgpu_desc->depthStoreOp());
+  dawn_desc.depthReadOnly = webgpu_desc->depthReadOnly();
 
   switch (webgpu_desc->stencilLoadValue()->GetContentType()) {
     case V8UnionGPULoadOpOrGPUStencilValue::ContentType::kGPULoadOp:
@@ -100,6 +101,7 @@
 
   dawn_desc.stencilStoreOp =
       AsDawnEnum<WGPUStoreOp>(webgpu_desc->stencilStoreOp());
+  dawn_desc.stencilReadOnly = webgpu_desc->stencilReadOnly();
 
   return dawn_desc;
 }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment.idl
index 9f189d46..a6faa51 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_depth_stencil_attachment.idl
@@ -9,7 +9,9 @@
 
     required (GPULoadOp or float) depthLoadValue;
     required GPUStoreOp depthStoreOp;
+    boolean depthReadOnly = false;
 
     required (GPULoadOp or GPUStencilValue) stencilLoadValue;
     required GPUStoreOp stencilStoreOp;
+    boolean stencilReadOnly = false;
 };
diff --git a/third_party/blink/renderer/platform/DEPS b/third_party/blink/renderer/platform/DEPS
index 3302568f..d7488eff 100644
--- a/third_party/blink/renderer/platform/DEPS
+++ b/third_party/blink/renderer/platform/DEPS
@@ -82,6 +82,7 @@
     "+ui/base/prediction",
     "+ui/base/resource/resource_scale_factor.h",
     "+ui/display/mojom",
+    "+ui/display/display.h",
     "+ui/display/screen_info.h",
     "+ui/display/screen_infos.h",
     "+ui/gfx",
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
index 572c0a42..bc058d9 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory.cc
@@ -13,7 +13,6 @@
 #include "media/video/gpu_video_accelerator_factories.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/platform/peerconnection/rtc_video_encoder.h"
-#include "third_party/blink/renderer/platform/webrtc/webrtc_video_utils.h"
 #include "third_party/webrtc/api/video_codecs/h264_profile_level_id.h"
 #include "third_party/webrtc/api/video_codecs/sdp_video_format.h"
 #include "third_party/webrtc/api/video_codecs/video_encoder.h"
@@ -144,6 +143,7 @@
 struct SupportedFormats {
   bool unknown = true;
   std::vector<media::VideoCodecProfile> profiles;
+  std::vector<std::vector<media::SVCScalabilityMode>> scalability_modes;
   std::vector<webrtc::SdpVideoFormat> sdp_formats;
 };
 
@@ -161,6 +161,7 @@
     absl::optional<webrtc::SdpVideoFormat> format = VEAToWebRTCFormat(profile);
     if (format) {
       supported_formats.profiles.push_back(profile.profile);
+      supported_formats.scalability_modes.push_back(profile.scalability_modes);
       supported_formats.sdp_formats.push_back(std::move(*format));
     }
   }
@@ -184,6 +185,18 @@
   return is_constrained_h264;
 }
 
+bool IsScalabiltiyModeSupported(
+    const std::string& scalability_mode,
+    const std::vector<media::SVCScalabilityMode>& supported_scalability_modes) {
+  for (const auto& supported_scalability_mode : supported_scalability_modes) {
+    if (scalability_mode ==
+        media::GetScalabilityModeName(supported_scalability_mode)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // anonymous namespace
 
 RTCVideoEncoderFactory::RTCVideoEncoderFactory(
@@ -240,38 +253,21 @@
 RTCVideoEncoderFactory::QueryCodecSupport(
     const webrtc::SdpVideoFormat& format,
     absl::optional<std::string> scalability_mode) const {
-  media::VideoCodec codec =
-      WebRtcToMediaVideoCodec(webrtc::PayloadStringToCodecType(format.name));
-  if (scalability_mode) {
-    absl::optional<int> spatial_layers =
-        WebRtcScalabilityModeSpatialLayers(*scalability_mode);
+  CheckAndWaitEncoderSupportStatusIfNeeded();
+  SupportedFormats supported_formats =
+      GetSupportedFormatsInternal(gpu_factories_);
 
-    // Check that the scalability mode was correctly parsed and that the
-    // configuration is valid (e.g., H264 doesn't support SVC at all and VP8
-    // doesn't support spatial layers).
-    if (!spatial_layers ||
-        (codec != media::VideoCodec::kVP8 && codec != media::VideoCodec::kVP9 &&
-         codec != media::VideoCodec::kAV1) ||
-        (codec == media::VideoCodec::kVP8 && *spatial_layers > 1)) {
-      // Ivalid scalability_mode, return unsupported.
-      return {false, false};
-    }
-    DCHECK(spatial_layers);
-    // Most HW encoders cannot handle spatial layers, so return false if the
-    // configuration contains spatial layers and spatial layers are not
-    // supported.
-    if (codec == media::VideoCodec::kVP9 && *spatial_layers > 1 &&
-        !RTCVideoEncoder::Vp9HwSupportForSpatialLayers()) {
-      return {false, false};
+  for (size_t i = 0; i < supported_formats.sdp_formats.size(); ++i) {
+    if (format.IsSameCodec(supported_formats.sdp_formats[i])) {
+      if (!scalability_mode ||
+          IsScalabiltiyModeSupported(*scalability_mode,
+                                     supported_formats.scalability_modes[i])) {
+        return {/*is_supported=*/true, /*is_power_efficient=*/true};
+      }
+      break;
     }
   }
-
-  if (format.IsCodecInList(GetSupportedFormats())) {
-    // Supported and power efficient.
-    return {true, true};
-  }
-  // Unsupported.
-  return {false, false};
+  return {/*is_supported=*/false, /*is_power_efficient=*/false};
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc
index f14ad53..7cda073 100644
--- a/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc
+++ b/third_party/blink/renderer/platform/peerconnection/rtc_video_encoder_factory_test.cc
@@ -5,6 +5,7 @@
 #include <stdint.h>
 
 #include "base/test/task_environment.h"
+#include "media/base/svc_scalability_mode.h"
 #include "media/base/video_codecs.h"
 #include "media/video/mock_gpu_video_accelerator_factories.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -22,7 +23,11 @@
     true, true};
 constexpr webrtc::VideoEncoderFactory::CodecSupport kUnsupported = {false,
                                                                     false};
-constexpr gfx::Size max_resolution = {1920, 1080};
+constexpr gfx::Size kMaxResolution = {1920, 1080};
+constexpr uint32_t kMaxFramerateNumerator = 30;
+constexpr uint32_t kMaxFramerateDenominator = 1;
+const std::vector<media::SVCScalabilityMode> kScalabilityModes = {
+    media::SVCScalabilityMode::kL1T2, media::SVCScalabilityMode::kL1T3};
 
 bool Equals(webrtc::VideoEncoderFactory::CodecSupport a,
             webrtc::VideoEncoderFactory::CodecSupport b) {
@@ -39,8 +44,10 @@
   absl::optional<media::VideoEncodeAccelerator::SupportedProfiles>
   GetVideoEncodeAcceleratorSupportedProfiles() override {
     media::VideoEncodeAccelerator::SupportedProfiles profiles = {
-        {media::VP8PROFILE_ANY, max_resolution, 30, 1},
-        {media::VP9PROFILE_PROFILE0, max_resolution, 30, 1}};
+        {media::VP8PROFILE_ANY, kMaxResolution, kMaxFramerateNumerator,
+         kMaxFramerateDenominator, kScalabilityModes},
+        {media::VP9PROFILE_PROFILE0, kMaxResolution, kMaxFramerateNumerator,
+         kMaxFramerateDenominator, kScalabilityModes}};
     return profiles;
   }
 };
@@ -90,23 +97,15 @@
 TEST_F(RTCVideoEncoderFactoryTest, QueryCodecSupportSvc) {
   EXPECT_CALL(mock_gpu_factories_, IsEncoderSupportKnown())
       .WillRepeatedly(Return(true));
-  // VP8 and VP9 supported for singles spatial layers.
+  // Test supported modes.
   EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP8"), "L1T2"),
                      kSupportedPowerEfficient));
   EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP9"), "L1T3"),
                      kSupportedPowerEfficient));
 
-  // VP9 support for spatial layers is conditionally supported/unsupported.
-  EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP9"), "L3T3"),
-                     RTCVideoEncoder::Vp9HwSupportForSpatialLayers()
-                         ? kSupportedPowerEfficient
-                         : kUnsupported));
-
-  // Valid SVC config but AV1 is not supported.
+  // Test unsupported modes.
   EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("AV1"), "L2T1"),
                      kUnsupported));
-
-  // Invalid SVC config even though VP8 is supported.
   EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("H264"), "L1T2"),
                      kUnsupported));
   EXPECT_TRUE(Equals(encoder_factory_.QueryCodecSupport(Sdp("VP8"), "L3T3"),
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 71442c6..75425a2 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1244,7 +1244,7 @@
     },
     {
       name: "LayoutNGBlockFragmentation",
-      implied_by: ["LayoutNGFlexFragmentation", "LayoutNGPrinting"],
+      implied_by: ["LayoutNGFlexFragmentation", "LayoutNGGridFragmentation", "LayoutNGPrinting"],
     },
     {
       name: "LayoutNGBlockInInline",
@@ -1281,6 +1281,12 @@
       status: "stable"
     },
     {
+      // Block fragmentation support in the grid layout algorithm.
+      // https://drafts.csswg.org/css-grid-1/#pagination
+      name: "LayoutNGGridFragmentation",
+      depends_on: ["LayoutNG"],
+    },
+    {
       name: "LayoutNGLayoutOverflowRecalc",
       depends_on: ["LayoutNG"],
       status: "stable",
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 67fcc9f..2254ea3 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -48,6 +48,7 @@
 #include "third_party/blink/renderer/platform/widget/input/widget_input_handler_manager.h"
 #include "third_party/blink/renderer/platform/widget/widget_base_client.h"
 #include "ui/base/ime/mojom/text_input_state.mojom-blink.h"
+#include "ui/display/display.h"
 #include "ui/display/screen_info.h"
 #include "ui/gfx/geometry/dip_util.h"
 #include "ui/gfx/presentation_feedback.h"
@@ -1405,8 +1406,13 @@
   // viewport size, which is set above.
   LayerTreeHost()->SetVisualDeviceViewportIntersectionRect(
       client_->ViewportVisibleRect());
-  LayerTreeHost()->SetDisplayColorSpaces(
-      screen_infos_.current().display_color_spaces);
+  if (display::Display::HasForceRasterColorProfile()) {
+    LayerTreeHost()->SetDisplayColorSpaces(gfx::DisplayColorSpaces(
+        display::Display::GetForcedRasterColorProfile()));
+  } else {
+    LayerTreeHost()->SetDisplayColorSpaces(
+        screen_infos_.current().display_color_spaces);
+  }
 
   if (orientation_changed)
     client_->OrientationChanged();
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 36441727..fe8de38 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -422,6 +422,10 @@
 crbug.com/432153 external/wpt/css/css-masking/mask-image/mask-image-url-image.html [ Failure ]
 crbug.com/432153 external/wpt/css/css-masking/mask-image/mask-image-url-remote-mask.html [ Failure ]
 crbug.com/432153 external/wpt/css/css-masking/mask-image/mask-image-url-image-hash.html [ Failure ]
+
+# CSS cascade layers
+crbug.com/1095765 external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
+
 # Fails, at a minimum, due to lack of support for CSS mask property in html elements
 crbug.com/432153 external/wpt/svg/painting/reftests/display-none-mask.html [ Skip ]
 
@@ -2813,15 +2817,6 @@
 crbug.com/626703 external/wpt/css/css-text-decor/text-emphasis-position-over-left-001.xht [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-pseudo/selection-background-painting-order.html [ Failure ]
 crbug.com/626703 external/wpt/css/css-text-decor/text-emphasis-position-under-right-001.xht [ Failure ]
-crbug.com/626703 [ Mac10.12 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
-crbug.com/626703 [ Mac10.13 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
-crbug.com/626703 [ Mac10.14 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
-crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
-crbug.com/626703 [ Mac11.0 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Failure ]
-crbug.com/626703 [ Win7 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Crash Failure ]
-crbug.com/626703 [ Linux ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Crash Failure ]
-crbug.com/626703 [ Mac10.15 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Crash Failure ]
-crbug.com/626703 [ Win10.20h2 ] external/wpt/css/css-cascade/layer-stylesheet-sharing.html [ Crash Failure ]
 crbug.com/626703 [ Linux ] external/wpt/infrastructure/testdriver/actions/eventOrder.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/input-events/input-events-cut-paste.html [ Failure Timeout ]
 crbug.com/626703 external/wpt/css/css-text-decor/text-emphasis-position-over-left-002.xht [ Failure ]
@@ -3688,7 +3683,7 @@
 
 crbug.com/899264 external/wpt/css/css-text/letter-spacing/letter-spacing-control-chars-001.html [ Failure ]
 
-crbug.com/1250666 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/invalid-image-pending-script.https.html [ Timeout Pass ]
+crbug.com/1250666 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/invalid-image-pending-script.https.html [ Pass Timeout ]
 
 crbug.com/829028 external/wpt/css/css-break/abspos-in-opacity-001.html [ Failure ]
 crbug.com/829028 external/wpt/css/css-break/avoid-border-break.html [ Failure ]
@@ -6845,8 +6840,8 @@
 crbug.com/1233826 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-cancel.https.html [ Crash Failure Pass ]
 # Also reported as failing via crbug.com/1233766:
 crbug.com/1233826 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-local-time-after-duration.https.html [ Crash Failure Pass ]
-crbug.com/1250666 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/overdraw.https.html [ Timeout Pass ]
-crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/invalid-image-paint-error.https.html [ Timeout Pass ]
+crbug.com/1250666 virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/overdraw.https.html [ Pass Timeout ]
+crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/invalid-image-paint-error.https.html [ Pass Timeout ]
 # Previously reported as failing via crbug.com/626703:
 crbug.com/1236558 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/no-op-animation.https.html [ Crash Failure Pass ]
 crbug.com/1233766 [ Mac ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-local-time-before-start.https.html [ Crash Failure Pass ]
@@ -6872,8 +6867,8 @@
 crbug.com/1249071 virtual/composite-clip-path-animation/external/wpt/css/css-masking/clip-path/animations/clip-path-animation-filter.html [ Crash Failure Pass ]
 
 # Sheriff 2021-09-08
-crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/valid-image-before-load.https.html [ Timeout Pass ]
-crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/valid-image-after-load.https.html [ Timeout Pass ]
+crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/valid-image-before-load.https.html [ Pass Timeout ]
+crbug.com/1250666 [ Mac ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/valid-image-after-load.https.html [ Pass Timeout ]
 crbug.com/1247758 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-composite-shadow-part4.html [ Crash Pass ]
 crbug.com/1247758 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-blending-color-over-pattern.html [ Crash Pass Timeout ]
 crbug.com/1247758 [ Mac ] virtual/oopr-canvas2d/fast/canvas/canvas-blending-pattern-over-image.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations
index 0accae4c..4d953bb 100644
--- a/third_party/blink/web_tests/WebGPUExpectations
+++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -156,9 +156,6 @@
 
 crbug.com/dawn/746 wpt_internal/webgpu/cts.html?q=webgpu:api,operation,shader_module,compilation_info:offset_and_length:valid=false;unicode=true [ Failure ]
 
-# Dawn is missing several validation rules about depthReadOnly/stencilReadOnly.
-crbug.com/dawn/485 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,render_pass,storeOp:* [ Failure ]
-
 crbug.com/1215024 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createComputePipeline:enrty_point_name_must_match:stageEntryPoint="main%5Cu0000";* [ Failure ]
 crbug.com/1215024 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createComputePipeline:enrty_point_name_must_match:stageEntryPoint="main%5Cu0000a";* [ Failure ]
 
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index ab9f72da..3553f44 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -103352,6 +103352,58 @@
        {}
       ]
      ],
+     "font-synthesis-small-caps-first-letter.html": [
+      "9e31777c73af5763c8c093fd6820becab033fe2a",
+      [
+       null,
+       [
+        [
+         "/css/css-fonts/font-synthesis-small-caps-first-letter-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "font-synthesis-small-caps-first-line.html": [
+      "77d66e58d8a8a3a58ccb352fad6ce9c71e3297a2",
+      [
+       null,
+       [
+        [
+         "/css/css-fonts/font-synthesis-small-caps-first-line-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "font-synthesis-small-caps-not-applied.html": [
+      "7e05b012ed03526b93ae2e3f221dd6b9e8b94868",
+      [
+       null,
+       [
+        [
+         "/css/css-fonts/font-synthesis-small-caps-not-applied-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "font-synthesis-small-caps.html": [
+      "953ebf5a3a3bf5d69a6ecfd3480b09a07410beb5",
+      [
+       null,
+       [
+        [
+         "/css/css-fonts/font-synthesis-small-caps-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "font-synthesis-style-binary.html": [
       "1391d9738611e204a3b720dcd378bb7587db3b7d",
       [
@@ -162205,7 +162257,7 @@
        ]
       ],
       "svg-document-styles-004.html": [
-       "9411440b30fa5a437da19aa567ed97f9e601abc0",
+       "1a7c139028634b72472240846c173e7b881d6b35",
        [
         null,
         [
@@ -162309,7 +162361,7 @@
        ]
       ],
       "svg-document-styles-012.html": [
-       "5f32ca132699b737734b1bf58e8ca44eacad0bc7",
+       "e649ef2ddf4866eafa5768217efcce5ec4337140",
        [
         null,
         [
@@ -162322,7 +162374,7 @@
        ]
       ],
       "svg-document-styles-013.html": [
-       "bec549fa3c43fb9b02138e4f6c1238699952c9be",
+       "e12bc8f0d4bc1bbb6f4c1f77f21d2c86fa9d43cb",
        [
         null,
         [
@@ -162335,7 +162387,7 @@
        ]
       ],
       "svg-document-styles-014.html": [
-       "c81d820e54b41c557da519b5a111f4d2d1ec987a",
+       "c7a43b158250bcff93c8cb3a48a243a0f03cd1cb",
        [
         null,
         [
@@ -162519,7 +162571,7 @@
        ]
       ],
       "svg-external-styles-014.html": [
-       "09de24e4e4589f7352bc09af81c67d36f7edea58",
+       "6ec267febef70a58e07a472bb5f91ee0ee19e5e1",
        [
         null,
         [
@@ -162588,7 +162640,7 @@
        ]
       ],
       "svg-transform-group-002.html": [
-       "5226c7acda866b472f063a5044e5a8b4771b37b5",
+       "cb4d7aac460d8da42aeee3eab5092d45ed83e923",
        [
         null,
         [
@@ -162627,7 +162679,7 @@
        ]
       ],
       "svg-transform-group-005.html": [
-       "2959d865eebf22e922b02699803a31ad0a60f838",
+       "5d5e5ada46af9ee3088b1a4892cd0aaac22ccb01",
        [
         null,
         [
@@ -162640,7 +162692,7 @@
        ]
       ],
       "svg-transform-group-006.html": [
-       "53ddbaa4f63c66bb1d3e8112a129d613174ecd05",
+       "2bbf77d26f7e75c9707336adef79241f3e52cbb8",
        [
         null,
         [
@@ -162705,7 +162757,7 @@
        ]
       ],
       "svg-transform-group-011.html": [
-       "749e770ec777b5029765cdaad91f1401dc6b91c1",
+       "59c4e77b2786339a5f007aaef7e0d0e14cb09403",
        [
         null,
         [
@@ -162770,7 +162822,7 @@
        ]
       ],
       "svg-transform-nested-005.html": [
-       "8a29213be2c7279d9e6460e7330e4df6e38446fa",
+       "ca693d2c34cec9006b00e472dba1db403dfae972",
        [
         null,
         [
@@ -162783,7 +162835,7 @@
        ]
       ],
       "svg-transform-nested-006.html": [
-       "068e1efdf4a1e5ca12ad223a575d227daa6b9799",
+       "91f1d3e857f24a9d1165e10a79070a67a92d667e",
        [
         null,
         [
@@ -162861,7 +162913,7 @@
        ]
       ],
       "svg-transform-nested-012.html": [
-       "ab2dff4f87429e55ff4636df01aeb2c783fda59d",
+       "a6571892df948e636c0163dc2f70c6cff1a5c5d5",
        [
         null,
         [
@@ -162900,7 +162952,7 @@
        ]
       ],
       "svg-transform-nested-015.html": [
-       "72f796ff6fa62010a37105555434ec223f724e6d",
+       "6ec40d41d396c5a991a5f1587f47b66db9781265",
        [
         null,
         [
@@ -162913,7 +162965,7 @@
        ]
       ],
       "svg-transform-nested-016.html": [
-       "f83d9dae62fe8d4fde4c30c6d297f9e2046d43c7",
+       "22db9eaebcf345aaf62a026e612d13ea405c156f",
        [
         null,
         [
@@ -162939,7 +162991,7 @@
        ]
       ],
       "svg-transform-nested-018.html": [
-       "755d0bfc02d2cbafccbf96d155b7315a15cd25e9",
+       "798078e872c22162581692be69ddb9fe2c6b66ce",
        [
         null,
         [
@@ -162965,7 +163017,7 @@
        ]
       ],
       "svg-transform-nested-020.html": [
-       "a4161a9ac946df5a74c2019af57f295b1f37acf4",
+       "a90af99610958cf204d02023b20b84b21db3020d",
        [
         null,
         [
@@ -162978,7 +163030,7 @@
        ]
       ],
       "svg-transform-nested-021.html": [
-       "7391e9d20834041c30a2a40b8b0c0ae38efa77da",
+       "3b8be89f3f7c30701cc6f870eddf2b3ed264eb72",
        [
         null,
         [
@@ -162991,7 +163043,7 @@
        ]
       ],
       "svg-transform-nested-022.html": [
-       "92444cf681b2b869d2a57c59bd5cf6a80e0b3b51",
+       "3ef4bba5a5624fc2abdabb6ca5dd8efdd6c1a6a5",
        [
         null,
         [
@@ -163004,7 +163056,7 @@
        ]
       ],
       "svg-transform-nested-023.html": [
-       "57f75277552eef5529a6b0108b453c2971d88391",
+       "a240df2f43edd96d06f1aff9fb1b6e613940b5fa",
        [
         null,
         [
@@ -163017,7 +163069,7 @@
        ]
       ],
       "svg-transform-nested-024.html": [
-       "2fd3feea26763373888cca45a62f1d194a930f91",
+       "baab7bfa874241e1708c73824ce3317076e05029",
        [
         null,
         [
@@ -163030,7 +163082,7 @@
        ]
       ],
       "svg-transform-nested-025.html": [
-       "b8836555db2a32c823733917ef3252ce2b857e92",
+       "68958f6f5189cc1be0cf70213a1f9445cae4c010",
        [
         null,
         [
@@ -163043,7 +163095,7 @@
        ]
       ],
       "svg-transform-nested-026.html": [
-       "192f14fdcd6b4432d54dec21e441784a59e95173",
+       "5c87506a031cd4fce12121e68aee72d17bec7c7f",
        [
         null,
         [
@@ -163056,7 +163108,7 @@
        ]
       ],
       "svg-transform-nested-027.html": [
-       "ec017a7e94e72059d901b4171fde6127e52f1450",
+       "f4119792ff8aab96b040114fbca719806dc61a6e",
        [
         null,
         [
@@ -163069,7 +163121,7 @@
        ]
       ],
       "svg-transform-nested-028.html": [
-       "cc806c0970166e9aa9a2ccb51a03410e72bffe13",
+       "69d88bc27212b469036e09ab18e76b66b5a80e71",
        [
         null,
         [
@@ -163082,7 +163134,7 @@
        ]
       ],
       "svg-transform-nested-029.html": [
-       "5bcb69a54dd4aaac8dcda56982e841e4ab66ba17",
+       "3a28c97a1c4e36d04f2e2ca7066ae475e5c9e828",
        [
         null,
         [
@@ -163398,7 +163450,7 @@
        ]
       ],
       "svg-inline-styles-014.html": [
-       "262382cc7c0f5fd517b516058f70e282b47a35dc",
+       "9d17363d1e4b3dc315ac7f0921e9ae5ad0920e75",
        [
         null,
         [
@@ -164232,7 +164284,7 @@
        ]
       ],
       "svg-matrix-064.html": [
-       "455a1b35502b6bba7da364796fe1ca5557241147",
+       "116acf9bea0803368555fb1a5f0e50c147322efb",
        [
         null,
         [
@@ -164245,7 +164297,7 @@
        ]
       ],
       "svg-matrix-065.html": [
-       "7b6d7412d2800b95e51cbc4755be2430dc35e287",
+       "b372f4b9ddbf9949fa8937159297974d2954982e",
        [
         null,
         [
@@ -164284,7 +164336,7 @@
        ]
       ],
       "svg-matrix-068.html": [
-       "10d44eed85a7ea6f840ce827ec874c1561b044af",
+       "7232ebe44daa43e01758a7e436ed2433f6965f3f",
        [
         null,
         [
@@ -164297,7 +164349,7 @@
        ]
       ],
       "svg-matrix-069.html": [
-       "34002901c74287cc5b049809249cb384cf248ed8",
+       "bf500336935b0167a8133a535a401b2c39d6b0b7",
        [
         null,
         [
@@ -164733,7 +164785,7 @@
        ]
       ],
       "svg-rotate-3args-invalid-001.html": [
-       "9bfab69b41f422cdb748cdf139f55d6cbc2f677a",
+       "f21063afbd9af48069ea09f08348a06fcee28809",
        [
         null,
         [
@@ -164746,7 +164798,7 @@
        ]
       ],
       "svg-rotate-3args-invalid-002.html": [
-       "0500d2953715260b364f91a16fa84941a07e01f7",
+       "6cdd6b179ddc30c826e7c1e6655488fb788aa1e5",
        [
         null,
         [
@@ -164759,7 +164811,7 @@
        ]
       ],
       "svg-rotate-3args-invalid-003.html": [
-       "43d37764aa53e497c11fa778f387f16d408279fc",
+       "d1b01eabb9268628b06d7c51064b1886c64ff8f3",
        [
         null,
         [
@@ -164772,7 +164824,7 @@
        ]
       ],
       "svg-rotate-3args-invalid-004.html": [
-       "277104c46131e8077a7081440d4d000284b78ed7",
+       "102807b280bb0af2135bf24ce7ff506e04e87b68",
        [
         null,
         [
@@ -164785,7 +164837,7 @@
        ]
       ],
       "svg-rotate-3args-invalid-005.html": [
-       "b426a70af31b257aafb7735dcfad256ef90fa662",
+       "0b48a82cbf3e404aa9b6008b0a6ddd8d1cc3039d",
        [
         null,
         [
@@ -166885,7 +166937,7 @@
        ]
       ],
       "svg-transform-list-separations-007.html": [
-       "94455681dc17255f6d7c8ecbc1f6ab6a68143083",
+       "e04a9053e8b24dd6bf522108b9f55ac7a68c6118",
        [
         null,
         [
@@ -167068,7 +167120,7 @@
      ],
      "transform-origin": {
       "svg-origin-length-001.html": [
-       "7e3ca917bf17f3428c72e750d05c140f9bb242f5",
+       "2f2256361cadd4f69aa08fd775a4305219a41fdd",
        [
         null,
         [
@@ -167081,7 +167133,7 @@
        ]
       ],
       "svg-origin-length-002.html": [
-       "924f38739141fb19468863805849a37e664ab378",
+       "d7d238c26e536d878270648aab3f7cda71598503",
        [
         null,
         [
@@ -167094,7 +167146,7 @@
        ]
       ],
       "svg-origin-length-003.html": [
-       "5304d1db5be4f0ef5bb426c54b1f0884996182a3",
+       "3afea97a7eeeabcd46e8d46001aad5b477c8abf9",
        [
         null,
         [
@@ -167107,7 +167159,7 @@
        ]
       ],
       "svg-origin-length-004.html": [
-       "ed61ec798ac40cb481f72c9b2068c63c77ecfd56",
+       "c33c9809c3d9575bbd77b32fb93bca368ab7c07c",
        [
         null,
         [
@@ -167120,7 +167172,7 @@
        ]
       ],
       "svg-origin-length-005.html": [
-       "9d7e30338c4e69f6abc4bc1ce3dfe84f87cd45f7",
+       "0f1d4d260f44364a079c87535064cd35f8979628",
        [
         null,
         [
@@ -167133,7 +167185,7 @@
        ]
       ],
       "svg-origin-length-006.html": [
-       "384a236acc4713aed77ac8d71b87589f0c3bb8b9",
+       "f29363483a43cd6fec821fb2e4622ae8d56f3904",
        [
         null,
         [
@@ -167146,7 +167198,7 @@
        ]
       ],
       "svg-origin-length-007.html": [
-       "94e942b9b0b9e2b90b49051d44c0e69d8380ccba",
+       "d1b067e0e7ab381993d657dc8b2c401ec4260c83",
        [
         null,
         [
@@ -167159,7 +167211,7 @@
        ]
       ],
       "svg-origin-length-008.html": [
-       "e17772b80ea9804fc882a48de95510eb71731a00",
+       "545cbe0132876c719378d0d22c7dd0eff3bab0e9",
        [
         null,
         [
@@ -167172,7 +167224,7 @@
        ]
       ],
       "svg-origin-length-cm-001.html": [
-       "84302dc8ae9785f975be43924a9512aca42d3ba4",
+       "6324edf6ca110c1a30d7293213dd5adc8b60df7c",
        [
         null,
         [
@@ -167185,7 +167237,7 @@
        ]
       ],
       "svg-origin-length-cm-002.html": [
-       "2346046ecc88a662f73a06b0ad08b770748138ac",
+       "83c1ffc814de17ff5d7f4b7e162e143862adeead",
        [
         null,
         [
@@ -167198,7 +167250,7 @@
        ]
       ],
       "svg-origin-length-cm-003.html": [
-       "35db5cf80461cccd277c9297230869129d973822",
+       "f20e0522224937bf5f92d8b33667d3f700f769a6",
        [
         null,
         [
@@ -167211,7 +167263,7 @@
        ]
       ],
       "svg-origin-length-cm-004.html": [
-       "f49ea0149d1482edb641932a4bc3cffa1a2e3a3c",
+       "09bd7735de17ecce47997eb8b88fa7a6884d040e",
        [
         null,
         [
@@ -167224,7 +167276,7 @@
        ]
       ],
       "svg-origin-length-cm-005.html": [
-       "442123000d88136e901b18f2fb6c3dcfc8540157",
+       "6c16f0e1112a070206f9ac60bbd3d293a0c088f5",
        [
         null,
         [
@@ -167237,7 +167289,7 @@
        ]
       ],
       "svg-origin-length-in-001.html": [
-       "a2736007e1bf8068c7fcf49f17ea447bd29ce998",
+       "4d2d58df2eb54cef50e4f74391b3019e2554a5c9",
        [
         null,
         [
@@ -167250,7 +167302,7 @@
        ]
       ],
       "svg-origin-length-in-002.html": [
-       "fbc3237845895d51d9ef065950254afbb7d476af",
+       "0bd200cfbe9506da5fefeac8afbe28426f5f251c",
        [
         null,
         [
@@ -167263,7 +167315,7 @@
        ]
       ],
       "svg-origin-length-in-003.html": [
-       "1f651aec1d6a42d857aacee4c2f1e7089cbd3f10",
+       "2108ef1840e07b57c61d9b41af13671b88203a9c",
        [
         null,
         [
@@ -167276,7 +167328,7 @@
        ]
       ],
       "svg-origin-length-in-004.html": [
-       "534f7b6a277e52a16a7c247b45c640f57ea6e559",
+       "ec44d317cc55a1902814921fb60ca0875fd7c208",
        [
         null,
         [
@@ -167289,7 +167341,7 @@
        ]
       ],
       "svg-origin-length-in-005.html": [
-       "a6b65666d40b8e66b435b11ee44ea1fc09d55980",
+       "98b33c25c1aa6073c1cff7f5a5e99c6aa4fc0a43",
        [
         null,
         [
@@ -167302,7 +167354,7 @@
        ]
       ],
       "svg-origin-length-pt-001.html": [
-       "b566533fd16ff71404ab0d0edbeea25089933468",
+       "6772fd10b9d9772c17b4128b5152e637cd25072f",
        [
         null,
         [
@@ -167315,7 +167367,7 @@
        ]
       ],
       "svg-origin-length-pt-002.html": [
-       "a9e2b06b9fc2dee64cb415cc5195e87858eda79b",
+       "94b4b58daeb69ccdc986a14e26459fffd7e3e63e",
        [
         null,
         [
@@ -167328,7 +167380,7 @@
        ]
       ],
       "svg-origin-length-pt-003.html": [
-       "55f12a66c9bb91abce16f36be66e498c59862b80",
+       "2d456b9c0165817d2508f386d5a93c38427a25e5",
        [
         null,
         [
@@ -167341,7 +167393,7 @@
        ]
       ],
       "svg-origin-length-pt-004.html": [
-       "9211b0b1642656a8bc75796812a7a52e4fd41073",
+       "494edb2a630fb0faf8c94b943311c3dfdb069097",
        [
         null,
         [
@@ -167354,7 +167406,7 @@
        ]
       ],
       "svg-origin-length-pt-005.html": [
-       "838c0953ad637f03e2e51c6752a6dbfe97a697d7",
+       "f3072823791799ad35a65520df1b3b16ed836abd",
        [
         null,
         [
@@ -167367,7 +167419,7 @@
        ]
       ],
       "svg-origin-relative-length-001.html": [
-       "f993beaaeff05251c659040f72b432984a020fd0",
+       "54e0031ee976eeaed15472928361411753a3a145",
        [
         null,
         [
@@ -167380,7 +167432,7 @@
        ]
       ],
       "svg-origin-relative-length-002.html": [
-       "7f40454e0e3412f2763ec10a1d834f3b21d4d6e0",
+       "ad58d8c4317d34872b2efa1850bd35c3aa42961e",
        [
         null,
         [
@@ -167393,7 +167445,7 @@
        ]
       ],
       "svg-origin-relative-length-003.html": [
-       "b4518f4d9f6b5580a18eee2bc6f4a9b3f0d251bb",
+       "65f4d6003508185285409474a2e8af1e318a1beb",
        [
         null,
         [
@@ -167406,7 +167458,7 @@
        ]
       ],
       "svg-origin-relative-length-004.html": [
-       "387f64d465b0563210983eb65070dbe2aa67bea2",
+       "3b76a772dfde703dcbbdba0a2dafc1d86fbb793c",
        [
         null,
         [
@@ -167419,7 +167471,7 @@
        ]
       ],
       "svg-origin-relative-length-005.html": [
-       "09d9453c1481f16a082a9ac68a59c43c634d6a7d",
+       "87e22fbe51f59a23dd1792ce9d2e2448e62ddfd7",
        [
         null,
         [
@@ -167432,7 +167484,7 @@
        ]
       ],
       "svg-origin-relative-length-006.html": [
-       "9946b19f409ddef1450245d5c5886e6fc72c5523",
+       "e74489e5136ec19d47d45d5fbe3652a994a0f242",
        [
         null,
         [
@@ -167445,7 +167497,7 @@
        ]
       ],
       "svg-origin-relative-length-007.html": [
-       "3cc11b94c92ba3ea2d266b8947024d380c104870",
+       "e03a8d0d138c06063399cc303aa8ec68603c76b0",
        [
         null,
         [
@@ -167458,7 +167510,7 @@
        ]
       ],
       "svg-origin-relative-length-008.html": [
-       "525f302b1f25f4852a50b47ac0ed63f4aca190c5",
+       "c9e9e3b70b05fbb4a0b971ea3d8f9951977eb6e6",
        [
         null,
         [
@@ -167471,7 +167523,7 @@
        ]
       ],
       "svg-origin-relative-length-009.html": [
-       "c469e4dea993adc2a4b81b461d9898fe3200d6d0",
+       "a40a998d90377a764d76c91ea03f1b4028bf24b5",
        [
         null,
         [
@@ -167484,7 +167536,7 @@
        ]
       ],
       "svg-origin-relative-length-010.html": [
-       "82f3ddc1752d2cc0448ab9e82c90f343df39cd16",
+       "0f4335dd1023fbde6e601df0e511c439d5aa1ab4",
        [
         null,
         [
@@ -167497,7 +167549,7 @@
        ]
       ],
       "svg-origin-relative-length-011.html": [
-       "e02c8f6dce787318b440116c9662775695688cf7",
+       "9ff00e621354cce7a4fb6bbad6617f5474af677b",
        [
         null,
         [
@@ -167510,7 +167562,7 @@
        ]
       ],
       "svg-origin-relative-length-012.html": [
-       "e2119ca917c156c870d2d66a7db6b04fd553b4f0",
+       "e3c8a9b672047a0645ed46fa3362d9db6e6d0e51",
        [
         null,
         [
@@ -167523,7 +167575,7 @@
        ]
       ],
       "svg-origin-relative-length-013.html": [
-       "fce55664e1009109acd0313ac1a559b3edec3057",
+       "b4977ea8e99e37d5aee6d2f2ac6e72092ea4764c",
        [
         null,
         [
@@ -167536,7 +167588,7 @@
        ]
       ],
       "svg-origin-relative-length-014.html": [
-       "fe239a0302ade218f6ba562b9ef650bd087386d5",
+       "6249beb7d5d6c08a7753e5285cf55e04897b2054",
        [
         null,
         [
@@ -167549,7 +167601,7 @@
        ]
       ],
       "svg-origin-relative-length-015.html": [
-       "08c48dc9232f4af59b2f71d190b88c6993f5d2a8",
+       "180f6cf8caca0211f13b2ae4718b35826c605100",
        [
         null,
         [
@@ -167562,7 +167614,7 @@
        ]
       ],
       "svg-origin-relative-length-016.html": [
-       "fb45b6b649a112b2c7e1e0eaac3d4048815becce",
+       "7a0b0128cce2702323d9172724a1826e84ef9da1",
        [
         null,
         [
@@ -167575,7 +167627,7 @@
        ]
       ],
       "svg-origin-relative-length-017.html": [
-       "70b35a2f5ecd8fe12acd8a9b72050f5d74487922",
+       "41abf1a0141991479a4467003108e69ae2c85956",
        [
         null,
         [
@@ -167588,7 +167640,7 @@
        ]
       ],
       "svg-origin-relative-length-018.html": [
-       "d59f922f9f41dafe4c509758dda00874a9d50d80",
+       "6252022d3f9aeb3d31a8600bf718d96446c79895",
        [
         null,
         [
@@ -167601,7 +167653,7 @@
        ]
       ],
       "svg-origin-relative-length-019.html": [
-       "b279cf3b5bf45aea157d9725485c88eb94c1f4fe",
+       "af42850b30583d26978d46d92f7acae66a4baa9b",
        [
         null,
         [
@@ -167614,7 +167666,7 @@
        ]
       ],
       "svg-origin-relative-length-020.html": [
-       "5f13e4db916cb60eed13724e6c9c919709423fec",
+       "8ca59aa90411d874244fc73b6fcd62dd1a36b169",
        [
         null,
         [
@@ -167627,7 +167679,7 @@
        ]
       ],
       "svg-origin-relative-length-021.html": [
-       "3a742bf2aa9291e5b12ea7d5e46cebff4f0505ac",
+       "5b3ce3373e2a5752c6d80fc11e5a6c4397dc92ee",
        [
         null,
         [
@@ -167640,7 +167692,7 @@
        ]
       ],
       "svg-origin-relative-length-022.html": [
-       "67c80842f281b4a7f0db58b70ec9089102221256",
+       "d6b4a25b88a8e14409c0a0c96a6a07bbbe8bfddb",
        [
         null,
         [
@@ -167653,7 +167705,7 @@
        ]
       ],
       "svg-origin-relative-length-023.html": [
-       "cb6dede80966a93ab1a85074ed2cb53b08c94db5",
+       "d7b0c77f4b645f2e2b25293333cf08b4f441b805",
        [
         null,
         [
@@ -167666,7 +167718,7 @@
        ]
       ],
       "svg-origin-relative-length-024.html": [
-       "b359d58a2cd4dbf6658059c9bcf03a48bdb34e31",
+       "24347e8cd49cff73004b3f274ffb64b91071ce2b",
        [
         null,
         [
@@ -167679,7 +167731,7 @@
        ]
       ],
       "svg-origin-relative-length-025.html": [
-       "3dff9d069fb9874bd65484ad4df4a4a56ae4b6dd",
+       "7cf1d16c044bf0422e800f6d6d21207f8d12a552",
        [
         null,
         [
@@ -167692,7 +167744,7 @@
        ]
       ],
       "svg-origin-relative-length-026.html": [
-       "26f018ba007485cf9309a8574ef7c47e06304ced",
+       "42d8044f58a137b1c1163278d37fc64e3c70b83b",
        [
         null,
         [
@@ -167705,7 +167757,7 @@
        ]
       ],
       "svg-origin-relative-length-027.html": [
-       "bb5f3c44c0a25244eff0e006e88db036314cd1ff",
+       "2e65ae445e37eb3d30d0f82ea8e47d0ab837eb99",
        [
         null,
         [
@@ -167718,7 +167770,7 @@
        ]
       ],
       "svg-origin-relative-length-028.html": [
-       "a615a4132f6b57cdc6ab117a29fc117ad5369e36",
+       "91c288e639241306d1607db08e9a61f4cf43ba52",
        [
         null,
         [
@@ -167731,7 +167783,7 @@
        ]
       ],
       "svg-origin-relative-length-029.html": [
-       "9f57db6827fcc49bd10067965c3b5724563ec8a1",
+       "0010c4d836d04845c5eec07397777f07107dd3aa",
        [
         null,
         [
@@ -167744,7 +167796,7 @@
        ]
       ],
       "svg-origin-relative-length-030.html": [
-       "286603dcc2dea70af70847efd8339116117a81be",
+       "a3c96c2a16758465e7cc3fcd74bb37fc885fe0b0",
        [
         null,
         [
@@ -167757,7 +167809,7 @@
        ]
       ],
       "svg-origin-relative-length-031.html": [
-       "0351910ba82b54a2f02dc4fcadf9a5b0032ad504",
+       "369be12dd2b3e5c0c9ff0d7c0efe891984fa2244",
        [
         null,
         [
@@ -167770,7 +167822,7 @@
        ]
       ],
       "svg-origin-relative-length-032.html": [
-       "81f07a3841348d9db3d0b8307e34e8b28e74ba50",
+       "40e79ba7d0d64f89bef1761e4efa3292f8e8cda6",
        [
         null,
         [
@@ -167783,7 +167835,7 @@
        ]
       ],
       "svg-origin-relative-length-033.html": [
-       "35f44452d0a2778b485b5754a210295a639d8107",
+       "9abce87f704d3e1522a834d9099913b32a84d364",
        [
         null,
         [
@@ -167796,7 +167848,7 @@
        ]
       ],
       "svg-origin-relative-length-034.html": [
-       "28bd7bac45bf98993fc5b1c3b1e8fbab8ab685f4",
+       "16c1eeebb8a7742e481623d56855e28c5a9a4f0f",
        [
         null,
         [
@@ -167809,7 +167861,7 @@
        ]
       ],
       "svg-origin-relative-length-035.html": [
-       "1cd4cf1fe66b54e221a8da66778f5cfd10713bc7",
+       "4a8c485673f66350114aef29321258706d55ee38",
        [
         null,
         [
@@ -167822,7 +167874,7 @@
        ]
       ],
       "svg-origin-relative-length-036.html": [
-       "3179f19ef351294fdd7f4b0b61259b6905a58ca2",
+       "ac39e86f9331991f54610212a7e550df08787bd8",
        [
         null,
         [
@@ -167835,7 +167887,7 @@
        ]
       ],
       "svg-origin-relative-length-037.html": [
-       "63fabab212ed5d0a3efc4a3ffda7ffd31e7494db",
+       "4a40e18760194feec992430eb2ddaace8c3c5c6a",
        [
         null,
         [
@@ -167848,7 +167900,7 @@
        ]
       ],
       "svg-origin-relative-length-038.html": [
-       "7e60e7f1038254db480f3f63d70555cd1c919033",
+       "50924a663c7eb7780f97b31b22474e7545624715",
        [
         null,
         [
@@ -167861,7 +167913,7 @@
        ]
       ],
       "svg-origin-relative-length-039.html": [
-       "7d787ab3ae3c1ce5b19ead72ad2abd858bf86063",
+       "2e2b446309c9e244b45fc565ee7acbdde84d8d84",
        [
         null,
         [
@@ -167874,7 +167926,7 @@
        ]
       ],
       "svg-origin-relative-length-040.html": [
-       "fa3ce910a57daa61488de29286794eab5ea2a571",
+       "3b46d2d22c891eb2f8389094219c86273c19c856",
        [
         null,
         [
@@ -167887,7 +167939,7 @@
        ]
       ],
       "svg-origin-relative-length-041.html": [
-       "6c04a3e0b71644730a1050f01c58904f3c220cd3",
+       "62189588a00eecfd5ef7f145c0c1de1995e25968",
        [
         null,
         [
@@ -167900,7 +167952,7 @@
        ]
       ],
       "svg-origin-relative-length-042.html": [
-       "65413a97e498ac5c7722cc935b74e2240339c0de",
+       "3e8f278d3170b7d5a78f3d76cbc1885ffd207631",
        [
         null,
         [
@@ -167913,7 +167965,7 @@
        ]
       ],
       "svg-origin-relative-length-043.html": [
-       "d274afab36a4de5dfedd8d3e691a3c9f69ec1e4f",
+       "b1d5a346c899f3c0139e91717caa23c4c7bf5464",
        [
         null,
         [
@@ -167926,7 +167978,7 @@
        ]
       ],
       "svg-origin-relative-length-044.html": [
-       "dc1f57c23324966d8f199625ed94cd7c05cfd67d",
+       "92944c7bf6ad58e31aa995aef2a554e2003cf2d6",
        [
         null,
         [
@@ -167939,7 +167991,7 @@
        ]
       ],
       "svg-origin-relative-length-045.html": [
-       "b5968f5fdafed2b6dedb7e0b1d34f2e0a04c5816",
+       "8af656ee7c2a13c0dc343078ab28e23d13cfdffa",
        [
         null,
         [
@@ -167952,7 +168004,7 @@
        ]
       ],
       "svg-origin-relative-length-046.html": [
-       "e80859621f65f8c5d77e40c6a5c2fae9b2a72664",
+       "29072ba1893bcb094d9b5e29225087a349d8d7bb",
        [
         null,
         [
@@ -167965,7 +168017,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-001.html": [
-       "9eefd9ed66693dda88895d0d767fdd4d363f7e97",
+       "a7e921169785b53d4a633bc76d692a7da155b6a9",
        [
         null,
         [
@@ -167978,7 +168030,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-002.html": [
-       "8a2513e03cef4108f5ff3ea00bc71d30ac1fa952",
+       "d9296ec019cf1d6089b14483988586f938a3271a",
        [
         null,
         [
@@ -167991,7 +168043,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-003.html": [
-       "d18555e9db7f4332fdbf3bf7e8f2c5cea4fbf7af",
+       "afee0ebc719d4e70fbce76fa4a1222d8c6af5537",
        [
         null,
         [
@@ -168004,7 +168056,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-004.html": [
-       "1a8010296f5b61d9783a62aa7dd26e1a8733c524",
+       "cdf1270bf8655a9ce4df584e01f0516b77d2ec17",
        [
         null,
         [
@@ -168017,7 +168069,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-005.html": [
-       "b75e10438d03756c122499c59fc0bdca3308392b",
+       "e06e6f47dc12913ae140ad68794c45c9c53745c1",
        [
         null,
         [
@@ -168030,7 +168082,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-006.html": [
-       "fcaf3a75af2f8dad724273a173442e9284fe0c53",
+       "09d02c5cdb908227868d2f7e2dca7e6bd5fd6e42",
        [
         null,
         [
@@ -168043,7 +168095,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-007.html": [
-       "3e4eb192273fc1a992f5e5dd0b113020b15225ec",
+       "727197b9755a61876e8d62382068b809066c3560",
        [
         null,
         [
@@ -168056,7 +168108,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-008.html": [
-       "5041d4ed5541a615c8a76a9c5934a16b5c5665fa",
+       "da91e511996b6119cf35eeab2ffa2a8b7e44f8be",
        [
         null,
         [
@@ -168069,7 +168121,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-009.html": [
-       "525daafaf0a0a34f72caea0312eef2d529932531",
+       "39dcbf4f73e8b8a39ac919d33f764d533f02a2da",
        [
         null,
         [
@@ -168082,7 +168134,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-010.html": [
-       "5c7b23bc962b8c56ca2dc59807c66736f97c025f",
+       "b13dd1e393bbdc23c180e1ff4df74500b589a4e8",
        [
         null,
         [
@@ -168095,7 +168147,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-011.html": [
-       "e66f3a03c829d880623b8d97bb77615eee1d6423",
+       "f53d7f0a79dfbf294f71f9394413c624e6639b7c",
        [
         null,
         [
@@ -168108,7 +168160,7 @@
        ]
       ],
       "svg-origin-relative-length-invalid-012.html": [
-       "25d90340b8d162793e37c783c7fd21aec2a6688e",
+       "69fe6f8129fce64c32d8d7c7d3b16196c6765747",
        [
         null,
         [
@@ -232989,6 +233041,22 @@
       "428c8c401856627c81bc7d03663317fd76bbf08b",
       []
      ],
+     "font-synthesis-small-caps-first-letter-ref.html": [
+      "8f66b7b298a7c247b6848527ac0fec1ee0de8286",
+      []
+     ],
+     "font-synthesis-small-caps-first-line-ref.html": [
+      "121f9412fb2e3768f6a24cf27347519b779bbcf2",
+      []
+     ],
+     "font-synthesis-small-caps-not-applied-ref.html": [
+      "6edfea421895199500b0775842b558a708d9443d",
+      []
+     ],
+     "font-synthesis-small-caps-ref.html": [
+      "6851d552674fe495f692e3a510e4aff4927c8f37",
+      []
+     ],
      "font-synthesis-style-binary-ref.html": [
       "8ab9ecd29535a7d44896b8b365ea72e0a0921c0d",
       []
@@ -245885,11 +245953,11 @@
      ],
      "parsing": {
       "marker-supported-properties-expected.txt": [
-       "4c34a3cdb2a8a95005917d8cd33c05982cc322cc",
+       "f99b2ca3319f820aac96b8967c124f6ad36af545",
        []
       ],
       "marker-supported-properties-in-animation-expected.txt": [
-       "3a8f97e9d515078336d3a4e0341411d78de346ea",
+       "6226c7d4ad64fdcae458fe867177af7835cff6bc",
        []
       ]
      },
@@ -255561,6 +255629,14 @@
       "888a51ea9b6ac04fb065ee5d84a18be8fe765aca",
       []
      ],
+     "exp-log-compute-expected.txt": [
+      "4e1e50ca14f202c8256ecd55d7188d43be56d118",
+      []
+     ],
+     "exp-log-serialize-expected.txt": [
+      "bac88b66be0f09636e63139c263996ad174807e4",
+      []
+     ],
      "minmax-angle-serialize-expected.txt": [
       "14d29fed17d1ef8eb55aa32757008bfa21a1bd87",
       []
@@ -266512,6 +266588,14 @@
      "b007264cea5db3c1ad6f2825ae44b149445dcaec",
      []
     ],
+    "local_FileSystemBaseHandle-move-manual.https-expected.txt": [
+     "68675641c404e9b6bcd81c36597a521afe64815c",
+     []
+    ],
+    "local_FileSystemBaseHandle-rename-manual.https-expected.txt": [
+     "7f803f9040382e74e1cd063224c4b5773e7de2f2",
+     []
+    ],
     "resources": {
      "data": {
       "testfile.txt": [
@@ -266572,6 +266656,22 @@
       []
      ]
     },
+    "sandboxed_FileSystemBaseHandle-move.https.any-expected.txt": [
+     "484a904eeb41013be55176031c6b1a7a2b8f704a",
+     []
+    ],
+    "sandboxed_FileSystemBaseHandle-move.https.any.worker-expected.txt": [
+     "484a904eeb41013be55176031c6b1a7a2b8f704a",
+     []
+    ],
+    "sandboxed_FileSystemBaseHandle-rename.https.any-expected.txt": [
+     "95afc342c93248f53dde56a17dd9cb015dd1bd66",
+     []
+    ],
+    "sandboxed_FileSystemBaseHandle-rename.https.any.worker-expected.txt": [
+     "95afc342c93248f53dde56a17dd9cb015dd1bd66",
+     []
+    ],
     "script-tests": {
      "FileSystemBaseHandle-IndexedDB.js": [
       "855e52f04ddf2f4f8641524010216c6e8c7cdda7",
@@ -266582,7 +266682,7 @@
       []
      ],
      "FileSystemBaseHandle-move.js": [
-      "2273a3594e77f37b91b15f606f6f40bc2182bc62",
+      "60885020ac156cf980eb552300aa8445863c6103",
       []
      ],
      "FileSystemBaseHandle-postMessage-BroadcastChannel.js": [
@@ -266622,7 +266722,7 @@
       []
      ],
      "FileSystemBaseHandle-rename.js": [
-      "cb9f766a0dc60133327d81903eb8ffa9ffbf98df",
+      "646f7c545b4911e3397d82f94a5b21f44388e1a7",
       []
      ],
      "FileSystemDirectoryHandle-getDirectoryHandle.js": [
@@ -279609,8 +279709,8 @@
         "d12943105f8c47d32f47eec0aa773a9a98046bfa",
         []
        ],
-       "selectmenu-shadow-root-replacement.tentative-expected.txt": [
-        "91050b8cf45e7ada0e77e0218067ca626b5e1d50",
+       "selectmenu-popup.tentative-expected.txt": [
+        "056f1af9c5bb3f1bf9eb3b4fda895738c556884f",
         []
        ],
        "support": {
@@ -280658,6 +280758,10 @@
            "ad5ab30eda15c3f755c8c00b3b81029432e242d9",
            []
           ],
+          "status-changing-script.py": [
+           "a44d3dd3eb0c0294f276d26ba319179ec5e9a2ff",
+           []
+          ],
           "v8-code-cache-iframe.sub.html": [
            "c3a870b3f1eeb93859b6adab4b89ad24c28016a7",
            []
@@ -280908,7 +281012,11 @@
           []
          ],
          "import-meta-url-expected.txt": [
-          "091a0cac3d66a7eb41c2c54d2985358ae5c26309",
+          "514f767553e18e524d4c965389d82f377eb85a10",
+          []
+         ],
+         "postmessage-worker.js": [
+          "3618137aef97a223c871439864386f3455eae0cb",
           []
          ]
         },
@@ -302269,19 +302377,19 @@
      ]
     },
     "idlharness.any-expected.txt": [
-     "0e1fde8457a207d6e2449dae4b9c085493831202",
+     "6ca7abd355ea362d5411d6311284903a83d67240",
      []
     ],
     "idlharness.any.serviceworker-expected.txt": [
-     "5ba489904e82d7ee96c0b32f55be6b5130a9146f",
+     "04d223ed62c85a9e4bb6e9be97f9b691a2549c1f",
      []
     ],
     "idlharness.any.sharedworker-expected.txt": [
-     "0e1fde8457a207d6e2449dae4b9c085493831202",
+     "6ca7abd355ea362d5411d6311284903a83d67240",
      []
     ],
     "idlharness.any.worker-expected.txt": [
-     "0e1fde8457a207d6e2449dae4b9c085493831202",
+     "6ca7abd355ea362d5411d6311284903a83d67240",
      []
     ],
     "quic": {
@@ -348852,14 +348960,14 @@
        ]
       ],
       "marker-supported-properties-in-animation.html": [
-       "df0e9bc6d34b3e8828d886bbe7ad3359f4178756",
+       "349c56d8ba08076c8889f3459f053192ea898628",
        [
         null,
         {}
        ]
       ],
       "marker-supported-properties.html": [
-       "62a54a338b7c401c05c16a59670f9d5cc2f30f8f",
+       "ab03b9825deee02142bd0a03a21e9ff95feaa82f",
        [
         null,
         {}
@@ -359199,6 +359307,27 @@
        {}
       ]
      ],
+     "exp-log-compute.html": [
+      "05ceadc5d1938a21730edc2bb520fe1a96382379",
+      [
+       null,
+       {}
+      ]
+     ],
+     "exp-log-invalid.html": [
+      "7fa56dc5bc196933c95b172587430896f4594d51",
+      [
+       null,
+       {}
+      ]
+     ],
+     "exp-log-serialize.html": [
+      "18f8f20b9c5e387de3be6908bbfdd8d2ef5c0b9d",
+      [
+       null,
+       {}
+      ]
+     ],
      "getComputedStyle-border-radius-001.html": [
       "6f3ba3ac4776045c94603b647d0a1ba134f5caf6",
       [
@@ -397319,7 +397448,7 @@
          ]
         ],
         "cross-document-nav-cross-document-traversal.html": [
-         "eed07f4c77bc7c96ed65a0f72bdbfa4efe7b1e7e",
+         "1173f3a39b9fbfe5c300e5ad2e25aa1e0aed5bcf",
          [
           null,
           {}
@@ -430890,7 +431019,7 @@
         ]
        ],
        "selectmenu-popup.tentative.html": [
-        "b43a8fed38b4e0bc16d91ee17183492921b92100",
+        "00c8441fbafec5b27a7ee2352890ce71f668d825",
         [
          null,
          {
@@ -430899,7 +431028,7 @@
         ]
        ],
        "selectmenu-shadow-root-replacement.tentative.html": [
-        "d999824245b466d1ed18a0bdcbb73ec363d951bd",
+        "bce00941e426f66b2d35c0a61d7bf081ab34dd54",
         [
          null,
          {
@@ -433706,7 +433835,7 @@
           ]
          ],
          "dynamic-imports-fetch-error.sub.html": [
-          "f000178842b95570537b5354e87a14056c9d296f",
+          "12738c7b9736e43df97610edebc3d4226e3299d3",
           [
            null,
            {}
@@ -434017,8 +434146,44 @@
          ]
         ],
         "import-meta": {
+         "import-meta-url.any.js": [
+          "82982b4d93cbf2588f82c4da94282dc0ea8a0ab3",
+          [
+           "html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.serviceworker-module.html",
+           {
+            "script_metadata": [
+             [
+              "global",
+              "dedicatedworker-module,sharedworker-module,serviceworker-module"
+             ]
+            ]
+           }
+          ],
+          [
+           "html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.sharedworker-module.html",
+           {
+            "script_metadata": [
+             [
+              "global",
+              "dedicatedworker-module,sharedworker-module,serviceworker-module"
+             ]
+            ]
+           }
+          ],
+          [
+           "html/semantics/scripting-1/the-script-element/module/import-meta/import-meta-url.any.worker-module.html",
+           {
+            "script_metadata": [
+             [
+              "global",
+              "dedicatedworker-module,sharedworker-module,serviceworker-module"
+             ]
+            ]
+           }
+          ]
+         ],
          "import-meta-url.html": [
-          "79f08ebaee3086b6454e41cc764162134c21b938",
+          "284a15f2b2317c5f25f3449038870730704944c8",
           [
            null,
            {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-004.html
index 9411440b..1a7c139 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-004.html
@@ -30,7 +30,7 @@
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
         <g class="testGroup" transform="scale(0.5)">
-            <rect width="100" height="100" fill="url(#grad)" transform="translateY(-100)"/>
+            <rect width="100" height="100" fill="url(#grad)" transform="translate(0 -100)"/>
         </g>
     </svg>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-012.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-012.html
index 5f32ca1..e649ef2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-012.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-012.html
@@ -15,7 +15,8 @@
             width: 300px;
         }
         rect.testRect {
-            transform: rotate(90deg,20px,20px);
+            transform: rotate(90deg);
+            transform-origin: 20px 20px;
         }
     </style>
 </head>
@@ -33,4 +34,4 @@
         <rect class="testRect" y="-60" width="100" height="100" fill="url(#grad)" transform="scale(0.5)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-013.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-013.html
index bec549f..e12bc8f0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-013.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-013.html
@@ -30,7 +30,7 @@
             </linearGradient>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect class="testRect" y="-60" width="100" height="100" fill="url(#grad)" transform="rotate(90,20px,20px)"/>
+        <rect class="testRect" y="-60" width="100" height="100" fill="url(#grad)" transform="rotate(90,20,20)"/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-014.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-014.html
index c81d820..c7a43b1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-014.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/document-styles/svg-document-styles-014.html
@@ -30,7 +30,7 @@
             </linearGradient>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect class="testRect" width="100" height="100" fill="url(#grad)" transform="rotate(90deg,invalid,invalid)"/>
+        <rect class="testRect" width="100" height="100" fill="url(#grad)" transform="rotate(90,invalid,invalid)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/external-styles/svg-external-styles-014.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/external-styles/svg-external-styles-014.html
index 09de24e4..6ec267fe 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/external-styles/svg-external-styles-014.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/external-styles/svg-external-styles-014.html
@@ -28,7 +28,7 @@
             </linearGradient>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect class="invalid" width="100" height="100" fill="url(#grad)" transform="rotate(90deg,)"/>
+        <rect class="invalid" width="100" height="100" fill="url(#grad)" transform="rotate(90,)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-002.html
index 5226c7a..cb4d7aa 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-002.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="translate(40px 0)">
+        <g transform="translate(40 0)">
             <rect y="40" width="80" height="80" fill="green"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-005.html
index 2959d86..5d5e5ad 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-005.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleX(2)">
+        <g transform="scale(2 1)">
             <rect x="20" y="40" width="40" height="80" fill="green"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-006.html
index 53ddbaa4..2bbf77d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-006.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleY(2)">
+        <g transform="scale(1 2)">
             <rect x="40" y="20" width="80" height="40" fill="green"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-011.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-011.html
index 749e770e..59c4e77 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-group-011.html
@@ -20,9 +20,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="rotate(90deg,20px,20px)">
+        <g transform="rotate(90,20,20)">
             <rect x="40" y="-80" width="80" height="80" fill="green"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-005.html
index 8a29213..ca693d2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-005.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleX(2)">
-            <rect x="10" y="40" width="20" height="80" fill="green" transform="scaleX(2)"/>
+        <g transform="scale(2 1)">
+            <rect x="10" y="40" width="20" height="80" fill="green" transform="scale(2 1)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-006.html
index 068e1ef..91f1d3e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-006.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleY(2)">
-            <rect x="40" y="10" width="80" height="20" fill="green" transform="scaleY(2)"/>
+        <g transform="scale(1 2)">
+            <rect x="40" y="10" width="80" height="20" fill="green" transform="scale(1 2)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-012.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-012.html
index ab2dff4f..a657189 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-012.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-012.html
@@ -20,8 +20,8 @@
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
         <g transform="translate(40 0)">
-            <rect y="20" width="80" height="40" fill="green" transform="scaleY(2)"/>
+            <rect y="20" width="80" height="40" fill="green" transform="scale(1 2)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-015.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-015.html
index 72f796f..6ec40d4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-015.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-015.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleX(2)">
+        <g transform="scale(2 1)">
             <rect x="40" y="-60" width="80" height="40" fill="green" transform="rotate(90)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-016.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-016.html
index f83d9da..22db9eae 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-016.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-016.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleY(2)">
+        <g transform="scale(1 2)">
             <rect y="20" width="80" height="40" fill="green" transform="translate(40 0)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-018.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-018.html
index 755d0bfc..798078e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-018.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-018.html
@@ -21,8 +21,9 @@
     <svg>
         <path d="M 2,1 100,1 198,99 100,99 Z" fill="red"/>
         <g transform="skewX(45)">
-            <rect width="200" height="100" fill="green" transform="scaleX(0.5)"/>
+            <!-- FIXME: This test will still pass if the transform= is ignored -->
+            <rect width="200" height="100" fill="green" transform="scale(0.5 1)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-020.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-020.html
index a4161a9a..a90af996 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-020.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-020.html
@@ -20,8 +20,8 @@
   <svg>
       <rect x="41" y="41" width="78" height="78" fill="red"/>
       <g transform="matrix(-1 0 0 -2 120 120)">
-          <rect width="40" height="40" fill="green" transform="scaleX(2)"/>
+          <rect width="40" height="40" fill="green" transform="scale(2 1)"/>
       </g>
   </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-021.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-021.html
index 7391e9d2..3b8be89f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-021.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-021.html
@@ -20,9 +20,9 @@
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
         <g transform="translate(20 20)">
-            <rect x="21" y="42" width="78" height="156" fill="red" transform="scaleY(0.5)"/> <!-- false positive if scaleY is negative; need to fix -->
+            <rect x="21" y="42" width="78" height="156" fill="red" transform="scale(1 0.5)"/> <!-- false positive if scaleY is negative; need to fix -->
             <rect x="20" y="-100" width="80" height="80" fill="green" transform="rotate(90)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-022.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-022.html
index 92444cf..3ef4bba5 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-022.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-022.html
@@ -20,9 +20,9 @@
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
         <g transform="translate(20 0)">
-            <rect x="42" y="41" width="156" height="78" fill="red" transform="scaleX(0.5)"/> <!-- false positive if scaleX is negative -->
+            <rect x="42" y="41" width="156" height="78" fill="red" transform="scale(0.5 1)"/> <!-- false positive if scaleX is negative -->
             <rect width="40" height="40" fill="green" transform="matrix(-2 0 0 -2 100 120)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-023.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-023.html
index 57f7527..a240df2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-023.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-023.html
@@ -19,10 +19,10 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
-        <g transform="translate(0 25px)">
-            <rect x="1" y="1" width="78" height="78" fill="red" transform="translate(40px 15px)"/>
+        <g transform="translate(0 25)">
+            <rect x="1" y="1" width="78" height="78" fill="red" transform="translate(40 15)"/>
             <rect x="80" y="30" width="160" height="160" fill="green" transform="scale(0.5)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-024.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-024.html
index 2fd3feea..baab7bf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-024.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-024.html
@@ -21,8 +21,8 @@
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
         <g transform="scale(0.5)">
             <rect x="62" y="82" width="156" height="156" fill="red" transform="translate(20 0)"/>
-            <rect x="160" y="80" width="320" height="160" fill="green" transform="scaleX(0.5)"/>
+            <rect x="160" y="80" width="320" height="160" fill="green" transform="scale(0.5 1)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-025.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-025.html
index b883655..68958f6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-025.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-025.html
@@ -19,10 +19,10 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
-        <g transform="scaleX(0.5)">
+        <g transform="scale(0.5 1)">
             <rect x="82" y="21" width="156" height="78" fill="red" transform="translate(0 20)"/>
             <rect x="160" y="80" width="320" height="160" fill="green" transform="scale(0.5)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-026.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-026.html
index 192f14fd..5c87506 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-026.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-026.html
@@ -19,10 +19,10 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
-        <g transform="scaleY(0.5)"> <!-- false positive if scaleY is negative; need to fix -->
+        <g transform="scale(1 0.5)"> <!-- false positive if scaleY is negative; need to fix -->
             <rect x="21" y="42" width="78" height="156" fill="red" transform="translate(20 40)"/>
             <rect x="80" y="-120" width="160" height="80" fill="green" transform="rotate(90)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-027.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-027.html
index ec017a7e..f4119792 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-027.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-027.html
@@ -21,8 +21,8 @@
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
         <g transform="rotate(90)">
             <rect x="20" y="-120" width="80" height="80" fill="green" transform="translate(20 0)"/>
-            <rect x="40" y="-240" width="80" height="160" fill="green" transform="scaleY(0.5)"/> <!-- false positive if scaleY is negative; need to fix -->
+            <rect x="40" y="-240" width="80" height="160" fill="green" transform="scale(1 0.5)"/> <!-- false positive if scaleY is negative; need to fix -->
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-028.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-028.html
index cc806c09..69d88bc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-028.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-028.html
@@ -20,9 +20,9 @@
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/> <!-- this rect is outside the group to catch failures of the group transform -->
         <g transform="matrix(-0.5 0 0 -0.5 120 90)">
-            <rect x="2" y="-116" width="156" height="312" fill="red" transform="scaleY(0.5)"/> <!-- false positive if scaleY is between 0.4 and -0.3 -->
+            <rect x="2" y="-116" width="156" height="312" fill="red" transform="scale(1 0.5)"/> <!-- false positive if scaleY is between 0.4 and -0.3 -->
             <rect width="160" height="160" fill="green" transform="translate(0 -60)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-029.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-029.html
index 5bcb69a5..3a28c97 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-029.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/group/svg-transform-nested-029.html
@@ -19,9 +19,9 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="41" y="41" width="78" height="78" fill="red"/>
-        <g transform="scaleX(2)">
-          <rect x="40" y="-20" width="80" height="40" fill="green" transform="rotate(90deg,20px,20px)"/>
+        <g transform="scale(2 1)">
+          <rect x="40" y="-20" width="80" height="40" fill="green" transform="rotate(90,20,20)"/>
         </g>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/inline-styles/svg-inline-styles-014.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/inline-styles/svg-inline-styles-014.html
index 262382c..9d17363d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/inline-styles/svg-inline-styles-014.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/inline-styles/svg-inline-styles-014.html
@@ -27,7 +27,7 @@
             </linearGradient>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect width="100" height="100" fill="url(#grad)" style="transform: scale(invalid)" transform="rotate(90deg,invalid,invalid)"/>
+        <rect width="100" height="100" fill="url(#grad)" style="transform: scale(invalid)" transform="rotate(90,invalid,invalid)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-064.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-064.html
index 455a1b3..116acf9b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-064.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-064.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
-		<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
+    <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
     <link rel="match" href="reference/svg-matrix-four-color-ref.html">
     <meta name="flags" content="svg">
     <meta name="assert" content="The matrix function does not support percentage values. If one argument is invalid in one function, none of the transforms in the function list should happen. The rect in this test should remain the same.">
@@ -28,7 +28,7 @@
             </pattern>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(50% 0 0 -0.5 100 100) translateX(100)"/>
+        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(50% 0 0 -0.5 100 100) translate(100 0)"/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-065.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-065.html
index 7b6d741..b372f4b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-065.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-065.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
-		<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
+    <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
     <link rel="match" href="reference/svg-matrix-four-color-ref.html">
     <meta name="flags" content="svg">
     <meta name="assert" content="The matrix function does not support radian units. If one argument is invalid in one function, none of the transforms in the function list should happen. The rect in this test should remain the same.">
@@ -28,7 +28,7 @@
             </pattern>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 45rad 0 -0.5 100 100) translateY(100)"/>
+        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 45rad 0 -0.5 100 100) translate(0 100)"/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-068.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-068.html
index 10d44ee..7232ebe 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-068.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-068.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
-		<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
+    <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
     <link rel="match" href="reference/svg-matrix-four-color-ref.html">
     <meta name="flags" content="svg">
     <meta name="assert" content="The matrix function does not support pc units. If one argument is invalid in one function, none of the transforms in the function list should happen. The rect in this test should remain the same.">
@@ -28,7 +28,7 @@
             </pattern>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 0 0.5 0.5 100pc 100) scaleX(0.5)"/>
+        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 0 0.5 0.5 100pc 100) scale(0.5 1)"/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-069.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-069.html
index 3400290..bf50033 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-069.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/matrix/svg-matrix-069.html
@@ -5,7 +5,7 @@
     <link rel="author" title="Rebecca Hauck" href="mailto:rhauck@adobe.com">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform">
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#two-d-transform-functions">
-		<link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
+    <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#funcdef-transform-matrix">
     <link rel="match" href="reference/svg-matrix-four-color-ref.html">
     <meta name="flags" content="svg">
     <meta name="assert" content="The matrix function does not support mm units. If one argument is invalid in one function, none of the transforms in the function list should happen. The rect in this test should remain the same.">
@@ -28,7 +28,7 @@
             </pattern>
         </defs>
         <rect x="1" y="1" width="98" height="98" fill="red"/>
-        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 0 0.5 0.5 100 100mm) scaleY(0.5)"/>
+        <rect width="100" height="100" fill="url(#coloredBoxes)" transform="matrix(0.5 0 0.5 0.5 100 100mm) scale(1 0.5)"/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-001.html
index 9bfab69b..f21063a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-001.html
@@ -7,7 +7,7 @@
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform-functions">
     <link rel="match" href="reference/svg-rotate-3args-ref.html">
     <meta name="flags" content="svg">
-    <meta name="assert" content="The rotate transform function takes two optional translation values. If one of the translation values is not provided, then both translation-value parameters fall back to zero. The green rect in this test should be rotated by 90 degrees clockwise but the transform origin should not be translated.  The green rect should completely cover the red rect.">
+    <meta name="assert" content="The rotate transform function takes two optional translation values. If one of the translation values is not provided, then the entire argument list is invalid and therefore no transform is applied. The green rect in this test should not be rotated.  The green rect should completely cover the red rect.">
     <style type="text/css">
     svg {
         width: 200px;
@@ -19,7 +19,7 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="1" y="1" width="78" height="78" fill="red"/>
-        <rect x="0" y="-80" width="80" height="80" fill="green" transform="rotate(90deg 20px)"/>
+        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90 20)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-002.html
index 0500d295..6cdd6b1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-002.html
@@ -19,7 +19,7 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="1" y="1" width="78" height="78" fill="red"/>
-        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90deg,)"/>
+        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90,)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-003.html
index 43d3776..d1b01ea 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-003.html
@@ -7,7 +7,7 @@
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform-functions">
     <link rel="match" href="reference/svg-rotate-3args-ref.html">
     <meta name="flags" content="svg">
-    <meta name="assert" content="The rotate transform function takes two optional translation values. If a third absolute translation-value argument is provided, then all translation-value parameters fall back to zero. The green rect in this test should be rotated by 90 degrees clockwise, but the transform origin should not be translated. The green rect should completely cover the red rect.">
+    <meta name="assert" content="The rotate transform function takes two optional translation values. If a third absolute translation-value argument is provided, then the entire argument list is invalid and therefore no transform is applied. The green rect in this test should not be rotated.  The green rect should completely cover the red rect.">
     <style type="text/css">
     svg {
         width: 200px;
@@ -19,7 +19,7 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="1" y="1" width="78" height="78" fill="red"/>
-        <rect x="0" y="-80" width="80" height="80" fill="green" transform="rotate(90deg,20px,20px,20px)"/>
+        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90,20,20,20)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-004.html
index 277104c4..102807b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-004.html
@@ -7,7 +7,7 @@
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform-functions">
     <link rel="match" href="reference/svg-rotate-3args-ref.html">
     <meta name="flags" content="svg">
-    <meta name="assert" content="The rotate transform function takes two optional translation values. If one of the translation values is not provided, then both translation-value parameters fall back to zero. The green rect in this test should be rotated by 90 degrees clockwise but the transform origin should not be translated.  The green rect should completely cover the red rect.">
+    <meta name="assert" content="The rotate transform function takes two optional translation values. If one of the translation values is not provided, then the entire argument list is invalid and therefore no transform is applied. The green rect in this test should not be rotated.  The green rect should completely cover the red rect.">
     <style type="text/css">
     svg {
         width: 200px;
@@ -19,7 +19,7 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="1" y="1" width="78" height="78" fill="red"/>
-        <rect x="0" y="-80" width="80" height="80" fill="green" transform="rotate(90deg 30%)"/>
+        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90 30%)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-005.html
index b426a70..0b48a82 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/rotate/svg-rotate-3args-invalid-005.html
@@ -7,7 +7,7 @@
     <link rel="help" href="http://www.w3.org/TR/css-transforms-1/#svg-transform-functions">
     <link rel="match" href="reference/svg-rotate-3args-ref.html">
     <meta name="flags" content="svg">
-    <meta name="assert" content="The rotate transform function takes two optional translation values. If a third relative translation-value argument is provided, then all translation-value parameters fall back to zero. The green rect in this test should be rotated by 90 degrees clockwise, but the transform origin should not be translated. The green rect should completely cover the red rect.">
+    <meta name="assert" content="The rotate transform function takes two optional translation values. If a third relative translation-value argument is provided, then the entire argument list is invalid and therefore no transform is applied. The green rect in this test should not be rotated.  The green rect should completely cover the red rect.">
     <style type="text/css">
     svg {
         width: 200px;
@@ -19,7 +19,7 @@
     <p>The test passes if there is a green square and no red.</p>
     <svg>
         <rect x="1" y="1" width="78" height="78" fill="red"/>
-        <rect x="0" y="-80" width="80" height="80" fill="green" transform="rotate(90deg,30%,20%,40%)"/>
+        <rect x="0" y="0" width="80" height="80" fill="green" transform="rotate(90,30%,20%,40%)"/>
     </svg>
 </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-list-separation/svg-transform-list-separations-007.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-list-separation/svg-transform-list-separations-007.html
index 94455681..e04a905 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-list-separation/svg-transform-list-separations-007.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-list-separation/svg-transform-list-separations-007.html
@@ -27,7 +27,7 @@
                 <stop offset="50%" stop-color="orange"/>
             </linearGradient>
         </defs>
-        <rect width="100" height="100" fill="url(#grad)" transform="      translateX(200),translateY(100)  rotate(45)rotate(45)      "/>
+        <rect width="100" height="100" fill="url(#grad)" transform="      translate(200 0),translate(0 100)  rotate(45)rotate(45)      "/>
     </svg>
 </body>
 </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-001.html
index 7e3ca91..2f22563 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-001.html
@@ -26,7 +26,7 @@
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="translate(100px, 0) rotate(90deg)" transform-origin=""/>
+     <rect width="100" height="100" fill="url(#grad)" transform="translate(100, 0) rotate(90)" transform-origin=""/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-002.html
index 924f387..d7d238c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-002.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="translate(100px, 0) rotate(90deg)" transform-origin="0 0"/>
+     <rect width="100" height="100" fill="url(#grad)" transform="translate(100, 0) rotate(90)" transform-origin="0 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-003.html
index 5304d1db..3afea97a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-003.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect x="100" width="100" height="100" fill="url(#grad)" transform="rotate(90deg)" transform-origin="100px 0"/>
+     <rect x="100" width="100" height="100" fill="url(#grad)" transform="rotate(90)" transform-origin="100px 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-004.html
index ed61ec79..c33c980 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-004.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90deg) translateX(-100px)" transform-origin="0 100px"/>
+     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90) translate(-100 0)" transform-origin="0 100px"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-005.html
index 9d7e3033..0f1d4d2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-005.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50px 50px"/>
+     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90)" transform-origin="50px 50px"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-006.html
index 384a236..f293634 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-006.html
@@ -26,7 +26,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect x="100" width="100" height="100" fill="url(#grad)" transform="rotate(90deg)" transform-origin="100 0"/>
+     <rect x="100" width="100" height="100" fill="url(#grad)" transform="rotate(90)" transform-origin="100 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-007.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-007.html
index 94e942b9..d1b067e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-007.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-007.html
@@ -26,7 +26,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90deg) translateX(-100px)" transform-origin="0 100"/>
+     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90) translate(-100 0)" transform-origin="0 100"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-008.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-008.html
index e17772b..545cbe0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-008.html
@@ -26,7 +26,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="98" height="98" fill="red"/>
-     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50 50"/>
+     <rect width="100" height="100" fill="url(#grad)" transform="rotate(90)" transform-origin="50 50"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-001.html
index 84302dc..6324edf6 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-001.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="73.590551181" height="73.590551181" fill="red"/>
-     <rect width="2cm" height="2cm" fill="url(#grad)" transform="translate(2cm, 0) rotate(90deg)" transform-origin=""/>
+     <rect width="2cm" height="2cm" fill="url(#grad)" transform="translate(75.5905512, 0) rotate(90)" transform-origin=""/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-002.html
index 2346046..83c1ffc8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-002.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="73.590551181" height="73.590551181" fill="red"/>
-     <rect width="2cm" height="2cm" fill="url(#grad)" transform="translate(2cm, 0) rotate(90deg)" transform-origin="0 0"/>
+     <rect width="2cm" height="2cm" fill="url(#grad)" transform="translate(75.5905512, 0) rotate(90)" transform-origin="0 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-003.html
index 35db5cf8..f20e052 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-003.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="73.590551181" height="73.590551181" fill="red"/>
-     <rect x="2cm" width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90deg)" transform-origin="2cm 0"/>
+     <rect x="2cm" width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90)" transform-origin="2cm 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-004.html
index f49ea01..09bd7735 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-004.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="73.590551181" height="73.590551181" fill="red"/>
-     <rect width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90deg) translateX(-2cm)" transform-origin="0 2cm"/>
+     <rect width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90) translate(-75.5905512 0)" transform-origin="0 2cm"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-005.html
index 4421230..6c16f0e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-cm-005.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="73.590551181" height="73.590551181" fill="red"/>
-     <rect width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90deg)" transform-origin="1cm 1cm"/>
+     <rect width="2cm" height="2cm" fill="url(#grad)" transform="rotate(90)" transform-origin="1cm 1cm"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-001.html
index a2736007..4d2d58d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-001.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="142" height="142" fill="red"/>
-     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="translate(1.5in, 0) rotate(90deg)" transform-origin=""/>
+     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="translate(144, 0) rotate(90)" transform-origin=""/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-002.html
index fbc3237..0bd200cf 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-002.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="142" height="142" fill="red"/>
-     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="translate(1.5in, 0) rotate(90deg)" transform-origin="0 0"/>
+     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="translate(144, 0) rotate(90)" transform-origin="0 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-003.html
index 1f651ae..2108ef18 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-003.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="142" height="142" fill="red"/>
-     <rect x="1.5in" width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90deg)" transform-origin="1.5in 0"/>
+     <rect x="1.5in" width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90)" transform-origin="1.5in 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-004.html
index 534f7b6a..ec44d31 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-004.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="142" height="142" fill="red"/>
-     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90deg) translateX(-1.5in)" transform-origin="0 1.5in"/>
+     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90) translate(-144 0)" transform-origin="0 1.5in"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-005.html
index a6b65666..98b33c25c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-in-005.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="142" height="142" fill="red"/>
-     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90deg)" transform-origin="0.75in 0.75in"/>
+     <rect width="1.5in" height="1.5in" fill="url(#grad)" transform="rotate(90)" transform-origin="0.75in 0.75in"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-001.html
index b566533..6772fd10 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-001.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="104.666666667" height="104.666666667" fill="red"/>
-     <rect width="80pt" height="80pt" fill="url(#grad)" transform="translate(80pt, 0) rotate(90deg)" transform-origin=""/>
+     <rect width="80pt" height="80pt" fill="url(#grad)" transform="translate(106.666667, 0) rotate(90)" transform-origin=""/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-002.html
index a9e2b06b..94b4b58 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-002.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="104.666666667" height="104.666666667" fill="red"/>
-     <rect width="80pt" height="80pt" fill="url(#grad)" transform="translate(80pt, 0) rotate(90deg)" transform-origin="0 0"/>
+     <rect width="80pt" height="80pt" fill="url(#grad)" transform="translate(106.6666667, 0) rotate(90)" transform-origin="0 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-003.html
index 55f12a6..2d456b9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-003.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="104.666666667" height="104.666666667" fill="red"/>
-     <rect x="80pt" width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90deg)" transform-origin="80pt 0"/>
+     <rect x="80pt" width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90)" transform-origin="80pt 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-004.html
index 9211b0b..494edb2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-004.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="104.666666667" height="104.666666667" fill="red"/>
-     <rect width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90deg) translateX(-80pt)" transform-origin="0 80pt"/>
+     <rect width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90) translate(-106.6666667 0)" transform-origin="0 80pt"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-005.html
index 838c0953..f307282 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-length-pt-005.html
@@ -25,7 +25,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="104.666666667" height="104.666666667" fill="red"/>
-     <rect width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90deg)" transform-origin="40pt 40pt"/>
+     <rect width="80pt" height="80pt" fill="url(#grad)" transform="rotate(90)" transform-origin="40pt 40pt"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-001.html
index f993beaa..54e0031e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-001.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="75"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="75"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-002.html
index 7f40454e..ad58d8c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-002.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-003.html
index b4518f4d..65f4d60 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-003.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="50%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-004.html
index 387f64d..3b76a77 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-004.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50% 50%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="50% 50%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-005.html
index 09d9453c..87e22fb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-005.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50% center"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="50% center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-006.html
index 9946b19..e74489e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-006.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center 50%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center 50%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-007.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-007.html
index 3cc11b94..e03a8d0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-007.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-007.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center center"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-008.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-008.html
index 525f302..c9e9e3b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-008.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="75 center"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="75 center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-009.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-009.html
index c469e4d..a40a998 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-009.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="75 50%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="75 50%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-010.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-010.html
index 82f3ddc1..0f4335d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-010.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-010.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center 75"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center 75"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-011.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-011.html
index e02c8f6d..9ff00e62 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-011.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="50% 75"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="50% 75"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-012.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-012.html
index e2119ca..e3c8a9b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-012.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-012.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="0"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-013.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-013.html
index fce55664..b4977ea8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-013.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-013.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="150"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="150"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-014.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-014.html
index fe239a0..6249beb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-014.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-014.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="100%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-015.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-015.html
index 08c48dc..180f6cf8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-015.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-015.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="right"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-016.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-016.html
index fb45b6b..7a0b012 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-016.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-016.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75)" transform-origin="left"/>
+     <rect x="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75)" transform-origin="left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-017.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-017.html
index 70b35a2..41abf1a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-017.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-017.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-37.5,-37.5)" transform-origin="25%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-37.5,-37.5)" transform-origin="25%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-018.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-018.html
index d59f922..6252022 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-018.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-018.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,-75)" transform-origin="top"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,-75)" transform-origin="top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-019.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-019.html
index b279cf3..af42850 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-019.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-019.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,75)" transform-origin="bottom"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,75)" transform-origin="bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-020.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-020.html
index 5f13e4d..8ca59aa 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-020.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-020.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="0% 0%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="0% 0%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-021.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-021.html
index 3a742bf2..5b3ce337 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-021.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-021.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="top right"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="top right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-022.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-022.html
index 67c8084..d6b4a25 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-022.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-022.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="top left"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="top left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-023.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-023.html
index cb6dede..d7b0c77f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-023.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-023.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="top center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="top center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-024.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-024.html
index b359d58..24347e8c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-024.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-024.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-225,75)" transform-origin="bottom left"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,75)" transform-origin="bottom left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-025.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-025.html
index 3dff9d0..7cf1d16 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-025.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-025.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-150,150)" transform-origin="bottom center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-150,150)" transform-origin="bottom center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-026.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-026.html
index 26f018b..42d8044 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-026.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-026.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,225)" transform-origin="bottom right"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,225)" transform-origin="bottom right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-027.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-027.html
index bb5f3c4..2e65ae445 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-027.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-027.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="right top"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-028.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-028.html
index a615a413..91c288e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-028.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-028.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(150)" transform-origin="right center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 150)" transform-origin="right center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-029.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-029.html
index 9f57db6..0010c4d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-029.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-029.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,225)" transform-origin="right bottom"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,225)" transform-origin="right bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
index 286603dc..a3c96c2 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-030.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="right 75"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right 75"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-031.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-031.html
index 0351910..369be12 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-031.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-031.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,75)" transform-origin="right 0%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,75)" transform-origin="right 0%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-032.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-032.html
index 81f07a3..40e79ba7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-032.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-032.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,225)" transform-origin="right 100%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,225)" transform-origin="right 100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-033.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-033.html
index 35f4445..9abce87 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-033.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-033.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="left top"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="left top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-034.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-034.html
index 28bd7bac4..16c1eee 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-034.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-034.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateX(-150)" transform-origin="left center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-150 0)" transform-origin="left center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-035.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-035.html
index 1cd4cf1..4a8c485 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-035.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-035.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-225,75)" transform-origin="left bottom"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,75)" transform-origin="left bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
index 3179f19e..ac39e86f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-036.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="left 75"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="left 75"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-037.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-037.html
index 63fabab..4a40e187 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-037.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-037.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-75,-75)" transform-origin="left 0%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-75,-75)" transform-origin="left 0%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-038.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-038.html
index 7e60e7f1..50924a66 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-038.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-038.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-225,75)" transform-origin="left 100%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,75)" transform-origin="left 100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-039.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-039.html
index 7d787ab..2e2b446 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-039.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-039.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center top"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-040.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-040.html
index fa3ce91..3b46d2d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-040.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-040.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-150,150)" transform-origin="center bottom"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-150,150)" transform-origin="center bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-041.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-041.html
index 6c04a3e0..62189588 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-041.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-041.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateX(-150)" transform-origin="center left"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-150 0)" transform-origin="center left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-042.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-042.html
index 65413a97e..3e8f278d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-042.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-042.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(150)" transform-origin="center right"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 150)" transform-origin="center right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-043.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-043.html
index d274afa..b1d5a34 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-043.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-043.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-150,150)" transform-origin="center 100%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-150,150)" transform-origin="center 100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
index dc1f57c2..92944c7 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-044.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(-225,-75)" transform-origin="0 center"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(-225,-75)" transform-origin="0 center"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-045.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-045.html
index b5968f5f..8af656e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-045.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-045.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg)" transform-origin="center 0%"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90)" transform-origin="center 0%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
index e808596..29072ba 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-046.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translate(75,-75)" transform-origin="center 0"/>
+     <rect x="75" y="75" width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(75,-75)" transform-origin="center 0"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html
index 9eefd9e..a7e9211 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-001.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="top 100%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="top 100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html
index 8a2513e..d9296ec0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-002.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="bottom 100%"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="bottom 100%"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html
index d18555e..afee0ebc 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-003.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="top 150"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="top 150"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html
index 1a80102..cdf1270 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-004.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="bottom 150"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="bottom 150"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-005.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-005.html
index b75e1043..e06e6f4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-005.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="top top"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="top top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-006.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-006.html
index fcaf3a75..09d02c5c 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-006.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="bottom bottom"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="bottom bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-007.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-007.html
index 3e4eb19..727197b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-007.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-007.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="top bottom"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="top bottom"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-008.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-008.html
index 5041d4e..da91e51 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-008.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="bottom top"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="bottom top"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-009.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-009.html
index 525daaf..39dcbf4f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-009.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="left left"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="left left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-010.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-010.html
index 5c7b23bc9..b13dd1e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-010.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-010.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="left right"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="left right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-011.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-011.html
index e66f3a0..f53d7f0a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-011.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="right right"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="right right"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-012.html b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-012.html
index 25d9034..69fe6f8 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-012.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-transforms/transform-origin/svg-origin-relative-length-invalid-012.html
@@ -14,6 +14,9 @@
       width: 200px;
       height: 200px;
     }
+    rect {
+      transform-box: fill-box;
+    }
   </style>
  </head>
  <body>
@@ -27,7 +30,7 @@
        </linearGradient>
      </defs>
      <rect x="1" y="1" width="148" height="148" fill="red"/>
-     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90deg) translateY(-150)" transform-origin="right left"/>
+     <rect width="150" height="150" fill="url(#grad)" transform="rotate(90) translate(0 -150)" transform-origin="right left"/>
    </svg>
  </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt
new file mode 100644
index 0000000..4e1e50ca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute-expected.txt
@@ -0,0 +1,20 @@
+This is a testharness.js-based test.
+FAIL log(1) should be used-value-equivalent to 0 assert_equals: log(1) and 0 serialize to the same thing in used values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none"
+FAIL log(10, 10) should be used-value-equivalent to 1 assert_equals: log(10, 10) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL exp(0) should be used-value-equivalent to 1 assert_equals: exp(0) and 1 serialize to the same thing in used values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL calc(log(e) ) should be used-value-equivalent to 1 Cannot read properties of undefined (reading 'split')
+FAIL calc(e - exp(1)) should be used-value-equivalent to 0 Cannot read properties of undefined (reading 'split')
+FAIL calc(log( 1 + 1 + 2 /2 - 2) ) should be used-value-equivalent to 0 Cannot read properties of undefined (reading 'split')
+PASS calc(log(1) + exp(0)) should be used-value-equivalent to 2
+PASS calc(exp(log(1) + exp(0)*2)) should be used-value-equivalent to 7.4
+PASS calc(log(log(1) + exp(0)*10)) should be used-value-equivalent to 2.3
+PASS calc(log(log(1) + exp(0)*20, 10)) should be used-value-equivalent to 1.3
+FAIL calc(log(e)  / log(e) + exp(0)*2 * log(e)) should be used-value-equivalent to 3 Cannot read properties of undefined (reading 'split')
+FAIL calc(log((1 + 1) /2)  / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 2 Cannot read properties of undefined (reading 'split')
+FAIL calc(log((3 + 1) /2, 2)  / log(e) + exp(0*1)*2 * log(e)) should be used-value-equivalent to 3 Cannot read properties of undefined (reading 'split')
+FAIL calc(log((3 + 1) /2, 2)  / log(e, e) + exp(0*1)*2 * log(e, e)) should be used-value-equivalent to 3 Cannot read properties of undefined (reading 'split')
+FAIL calc(exp(0) + 1) should be used-value-equivalent to 2 Cannot read properties of undefined (reading 'split')
+FAIL calc(log(exp(1))) should be used-value-equivalent to 1 Cannot read properties of undefined (reading 'split')
+FAIL calc(log(exp(log(e)))) should be used-value-equivalent to 1 Cannot read properties of undefined (reading 'split')
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html
new file mode 100644
index 0000000..05ceadc5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-compute.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/numeric-testcommon.js"></script>
+<div id="target"></div>
+<script>
+// Simple tests
+test_math_used('log(1)', '0', {type:'number'});
+test_math_used('log(10, 10)', '1', {type:'number'});
+test_math_used('exp(0)', '1', {type:'number'});
+
+// Test e
+test_math_used('calc(log(e) )', '1', {type:'number', approx:0.1});
+test_math_used('calc(e - exp(1))', '0', {type:'number', approx:0.1});
+
+//General calculations
+test_math_used('calc(log( 1 + 1 + 2 /2 - 2) )', '0', {type:'number', approx:0.1});
+test_math_used('calc(log(1) + exp(0))', '2'), {type:'number', approx:0.1};
+test_math_used('calc(exp(log(1) + exp(0)*2))', '7.4'), {type:'number', approx:0.1};
+test_math_used('calc(log(log(1) + exp(0)*10))', '2.3'), {type:'number', approx:0.1};
+test_math_used('calc(log(log(1) + exp(0)*20, 10))', '1.3'), {type:'number', approx:0.1};
+test_math_used('calc(log(e)  / log(e) + exp(0)*2 * log(e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(log((1 + 1) /2)  / log(e) + exp(0*1)*2 * log(e))', '2', {type:'number', approx:0.1});
+test_math_used('calc(log((3 + 1) /2, 2)  / log(e) + exp(0*1)*2 * log(e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(log((3 + 1) /2, 2)  / log(e, e) + exp(0*1)*2 * log(e, e))', '3', {type:'number', approx:0.1});
+test_math_used('calc(exp(0) + 1)', '2', {type:'number', approx:0.1});
+
+// Test nesting
+test_math_used('calc(log(exp(1)))', '1', {type:'number', approx:0.1});
+test_math_used('calc(log(exp(log(e))))', '1', {type:'number', approx:0.1});
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-invalid.html
new file mode 100644
index 0000000..7fa56dc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-invalid.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-type-checking">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/parsing-testcommon.js"></script>
+<script>
+function test_invalid_number(value) {
+  test_invalid_value('opacity', value);
+}
+
+// Syntax checking
+test_invalid_number('exp()');
+test_invalid_number('exp( )');
+test_invalid_number('exp(,)');
+test_invalid_number('exp(1, )');
+test_invalid_number('exp(, 1)');
+test_invalid_number('exp(1 + )');
+test_invalid_number('exp(1 - )');
+test_invalid_number('exp(1 * )');
+test_invalid_number('exp(1 / )');
+test_invalid_number('exp(1 2)');
+test_invalid_number('exp(1, , 2)');
+test_invalid_number('log()');
+test_invalid_number('log( )');
+test_invalid_number('log(,)');
+test_invalid_number('log(1, )');
+test_invalid_number('log(, 1)');
+test_invalid_number('log(1 + )');
+test_invalid_number('log(1 - )');
+test_invalid_number('log(1 * )');
+test_invalid_number('log(1 / )');
+test_invalid_number('log(1 2)');
+test_invalid_number('log(1, , 2)');
+
+// Type checking
+test_invalid_number('exp(0px)');
+test_invalid_number('exp(0s)');
+test_invalid_number('exp(0deg)');
+test_invalid_number('exp(0Hz)');
+test_invalid_number('exp(0dpi)');
+test_invalid_number('exp(0fr)');
+test_invalid_number('exp(1, 1%)');
+test_invalid_number('exp(1, 0px)');
+test_invalid_number('exp(1, 0s)');
+test_invalid_number('exp(1, 0deg)');
+test_invalid_number('exp(1, 0Hz)');
+test_invalid_number('exp(1, 0dpi)');
+test_invalid_number('exp(1, 0fr)');
+test_invalid_number('log(0px)');
+test_invalid_number('log(0s)');
+test_invalid_number('log(0deg)');
+test_invalid_number('log(0Hz)');
+test_invalid_number('log(0dpi)');
+test_invalid_number('log(0fr)');
+test_invalid_number('log(1, 1%)');
+test_invalid_number('log(1, 0px)');
+test_invalid_number('log(1, 0s)');
+test_invalid_number('log(1, 0deg)');
+test_invalid_number('log(1, 0Hz)');
+test_invalid_number('log(1, 0dpi)');
+test_invalid_number('log(1, 0fr)');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize-expected.txt
new file mode 100644
index 0000000..bac88b6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize-expected.txt
@@ -0,0 +1,19 @@
+This is a testharness.js-based test.
+FAIL 'exp(0)' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'exp(0)' should be valid in opacity. got disallowed value ""
+FAIL 'scale(exp(0))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(exp(0))' should be valid in transform. got disallowed value ""
+PASS 'exp(0)' as a computed value should serialize as '1'.
+FAIL 'scale(exp(0))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(exp(0))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL 'log(1)' as a specified value should serialize as 'calc(0)'. assert_not_equals: 'log(1)' should be valid in opacity. got disallowed value ""
+FAIL 'scale(log(1))' as a specified value should serialize as 'scale(calc(0))'. assert_not_equals: 'scale(log(1))' should be valid in transform. got disallowed value ""
+FAIL 'log(1)' as a computed value should serialize as '0'. assert_equals: 'log(1)' and '0' should serialize the same in computed values. expected "0" but got "1"
+FAIL 'scale(log(1))' as a computed value should serialize as 'matrix(0, 0, 0, 0, 0, 0)'. assert_equals: 'scale(log(1))' and 'matrix(0, 0, 0, 0, 0, 0)' should serialize the same in computed values. expected "matrix(0, 0, 0, 0, 0, 0)" but got "none"
+FAIL 'calc(exp(0) + log(1) + log(1))' as a specified value should serialize as 'calc(1)'. assert_not_equals: 'calc(exp(0) + log(1) + log(1))' should be valid in opacity. got disallowed value ""
+FAIL 'scale(calc(exp(0) + log(1) + log(1)))' as a specified value should serialize as 'scale(calc(1))'. assert_not_equals: 'scale(calc(exp(0) + log(1) + log(1)))' should be valid in transform. got disallowed value ""
+PASS 'calc(exp(0) + log(1) + log(1))' as a computed value should serialize as '1'.
+FAIL 'scale(calc(exp(0) + log(1) + log(1)))' as a computed value should serialize as 'matrix(1, 0, 0, 1, 0, 0)'. assert_equals: 'scale(calc(exp(0) + log(1) + log(1)))' and 'matrix(1, 0, 0, 1, 0, 0)' should serialize the same in computed values. expected "matrix(1, 0, 0, 1, 0, 0)" but got "none"
+FAIL 'calc(log(1) + 0.5)' as a specified value should serialize as 'calc(0.5)'. assert_not_equals: 'calc(log(1) + 0.5)' should be valid in opacity. got disallowed value ""
+FAIL 'scale(calc(log(1) + 0.5))' as a specified value should serialize as 'scale(calc(0.5))'. assert_not_equals: 'scale(calc(log(1) + 0.5))' should be valid in transform. got disallowed value ""
+FAIL 'calc(log(1) + 0.5)' as a computed value should serialize as '0.5'. assert_equals: 'calc(log(1) + 0.5)' and '0.5' should serialize the same in computed values. expected "0.5" but got "1"
+FAIL 'scale(calc(log(1) + 0.5))' as a computed value should serialize as 'matrix(0.5, 0, 0, 0.5, 0, 0)'. assert_equals: 'scale(calc(log(1) + 0.5))' and 'matrix(0.5, 0, 0, 0.5, 0, 0)' should serialize the same in computed values. expected "matrix(0.5, 0, 0, 0.5, 0, 0)" but got "none"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize.html b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize.html
new file mode 100644
index 0000000..18f8f20
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/exp-log-serialize.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#comp-func">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#numbers">
+<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-serialize">
+<link rel="author" title="Apple Inc">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../support/serialize-testcommon.js"></script>
+<div id=target></div>
+<script>
+function test_serialization(t,s,c) {
+    test_specified_serialization('opacity', t, s);
+    test_specified_serialization('transform', `scale(${t})`, `scale(${s})`);
+    test_computed_serialization('opacity', t, c);
+    test_computed_serialization('transform', `scale(${t})`, `matrix(${c}, 0, 0, ${c}, 0, 0)`);
+}
+
+test_serialization(
+    'exp(0)',
+    'calc(1)',
+    '1');
+test_serialization(
+    'log(1)',
+    'calc(0)',
+    '0');
+
+test_serialization(
+    'calc(exp(0) + log(1) + log(1))',
+    'calc(1)',
+    '1');
+
+test_serialization(
+    'calc(log(1) + 0.5)',
+    'calc(0.5)',
+    '0.5');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/tentative/cross-document-nav-cross-document-traversal.html b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/tentative/cross-document-nav-cross-document-traversal.html
index eed07f4c..1173f3a3 100644
--- a/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/tentative/cross-document-nav-cross-document-traversal.html
+++ b/third_party/blink/web_tests/external/wpt/html/browsers/browsing-the-web/overlapping-navigations-and-traversals/tentative/cross-document-nav-cross-document-traversal.html
@@ -34,5 +34,5 @@
 
   await waitForLoad(iframe);
   assert_equals(iframe.contentWindow.location.search, "?1", "must go back one step eventually");
-}, "cross-document navigations are stopped by same-document back()");
+}, "cross-document navigations are stopped by cross-document back()");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html
index 1618f40..7ff672d 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/css-module-worker-test.html
@@ -3,34 +3,51 @@
 <head>
     <script src="/resources/testharness.js"></script>
     <script src="/resources/testharnessreport.js"></script>
+    <script src="/common/utils.js"></script>
 </head>
 
 <body>
     <script>
         setup({allow_uncaught_exception: true});
-        async_test(function (test) {
-            const worker = new Worker("./resources/worker.js", {
+        promise_test(function (test) {
+            const uuid = token();
+            const worker = new Worker(`./resources/worker.sub.js?key=${uuid}`, {
                 type: "module"
             });
-            worker.onmessage = test.unreached_func("A CSS Module within a web worker should not load.");
-            worker.onerror = test.step_func_done();
-        }, "A static import CSS Module within a web worker should not load.");
+            return new Promise((resolve, reject) => {
+                worker.addEventListener("error", resolve);
+                worker.addEventListener("message", reject);
+            }).then(async () => {
+                const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`);
+                const fetchData = await fetchResponse.json();
+                assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker");
+            });
+        }, "A static import CSS Module within a web worker should not load and should not attempt to fetch the module.");
 
-        async_test(function (test) {
-            const worker = new Worker("./resources/worker-dynamic-import.js", {
+        promise_test(function (test) {
+            const uuid = token();
+            const worker = new Worker(`./resources/worker-dynamic-import.sub.js?key=${uuid}`, {
                 type: "module"
             });
-            worker.onmessage = test.step_func_done(e => {
-                assert_equals(e.data, "NOT LOADED");
-            });
-        }, "A dynamic import CSS Module within a web worker should not load.");
 
-        async_test(function (test) {
+            return new Promise(resolve => {
+                worker.addEventListener("message", resolve);
+            }).then(async (event) => {
+                assert_equals(event.data, "NOT LOADED");
+                const fetchResponse = await fetch(`./resources/record-fetch.py?key=${uuid}&action=getCount`);
+                const fetchData = await fetchResponse.json();
+                assert_equals(fetchData.count, 0, "Shouldn't have tried fetching CSS module in worker");
+            });
+        }, "A dynamic import CSS Module within a web worker should not load and should not attempt to fetch the module.");
+
+        promise_test(function (test) {
             const worker = new Worker("./resources/basic.css", {
                 type: "module"
             });
-            worker.onerror = test.step_func_done();
-        }, "A CSS Module within a web worker should not load.");
+            return new Promise(resolve => {
+                worker.onerror = resolve;
+            });
+        }, "An attempt to load a CSS module as a worker should fail.");
 
     </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py
new file mode 100644
index 0000000..4928cb4a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/record-fetch.py
@@ -0,0 +1,20 @@
+def main(request, response):
+    try:
+        stash_key = request.GET.first(b"key")
+        action = request.GET.first(b"action")
+
+        run_count = request.server.stash.take(stash_key)
+        if not run_count:
+            run_count = 0
+
+        if action == b"incCount":
+            request.server.stash.put(stash_key, run_count + 1)
+            response.headers.set(b"Content-Type", b"text/css")
+            response.content = b'#test { background-color: #FF0000; }'
+        elif action == b"getCount":
+            response.headers.set(b"Content-Type", b"text/json")
+            response.content = b'{"count": %d }' % run_count
+        else:
+            response.set_error(400, u"Invalid action")
+    except:
+        response.set_error(400, u"Not enough parameters")
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.js
deleted file mode 100644
index 6f6852c..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import("./basic.css", { assert: { type: "css" } })
-  .then(() => postMessage("LOADED"))
-  .catch(e => postMessage("NOT LOADED"));
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js
new file mode 100644
index 0000000..791bd7d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker-dynamic-import.sub.js
@@ -0,0 +1,3 @@
+import("./record-fetch.py?key={{GET[key]}}&action=incCount", { assert: { type: "css" } })
+  .then(() => postMessage("LOADED"))
+  .catch(e => postMessage("NOT LOADED"));
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.js
deleted file mode 100644
index c97d9652..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import "./basic.css" assert { type: "css" };
-postMessage("Unexpectedly loaded");
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js
new file mode 100644
index 0000000..ffee312
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/css-module/resources/worker.sub.js
@@ -0,0 +1,2 @@
+import "./record-fetch.py?key={{GET[key]}}&action=incCount" assert { type: "css" };
+postMessage("Unexpectedly loaded");
\ No newline at end of file
diff --git a/third_party/cast_core/LICENSE b/third_party/cast_core/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/third_party/cast_core/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
\ No newline at end of file
diff --git a/third_party/cast_core/OWNERS b/third_party/cast_core/OWNERS
new file mode 100644
index 0000000..d6722472
--- /dev/null
+++ b/third_party/cast_core/OWNERS
@@ -0,0 +1,3 @@
+shawnq@google.com
+
+file://chromecast/OWNERS
\ No newline at end of file
diff --git a/third_party/cast_core/README.chromium b/third_party/cast_core/README.chromium
new file mode 100644
index 0000000..e7d7c75
--- /dev/null
+++ b/third_party/cast_core/README.chromium
@@ -0,0 +1,15 @@
+Name: CastCore Publics
+Short Name: cast_core/public
+URL: https://chromium.googlesource.com/cast_core/public
+Version: 0
+Date: 2021/09/14
+Revision: 21e7e00e13122d83507449578c6bfe356d7eb266
+License: Apache 2.0
+License File: LICENSE
+Security Critical: yes
+
+Description:
+Public components, such as protos, used by gRPC-based CastCore services and
+clients.
+
+Local Modifications: None
\ No newline at end of file
diff --git a/third_party/wayland-protocols/BUILD.gn b/third_party/wayland-protocols/BUILD.gn
index 64c87ea9..17ab1a0 100644
--- a/third_party/wayland-protocols/BUILD.gn
+++ b/third_party/wayland-protocols/BUILD.gn
@@ -65,7 +65,10 @@
 }
 
 wayland_protocol("remote_shell_protocol") {
-  sources = [ "unstable/remote-shell/remote-shell-unstable-v1.xml" ]
+  sources = [
+    "unstable/remote-shell/remote-shell-unstable-v1.xml",
+    "unstable/remote-shell/remote-shell-unstable-v2.xml",
+  ]
 }
 
 wayland_protocol("gaming_input_protocol") {
diff --git a/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v2.xml b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v2.xml
new file mode 100644
index 0000000..622ebea
--- /dev/null
+++ b/third_party/wayland-protocols/unstable/remote-shell/remote-shell-unstable-v2.xml
@@ -0,0 +1,978 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="remote_shell_unstable_v2">
+
+  <copyright>
+    Copyright 2021 The Chromium Authors.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <description summary="Create remote desktop-style surfaces">
+    remote_shell allows clients to turn a wl_surface into a "real window"
+    which can be stacked and activated by the user.
+
+    Warning! The protocol described in this file is experimental and backward
+    incompatible changes may be made. Backward compatible changes may be added
+    together with the corresponding interface version bump. Backward
+    incompatible changes are done by bumping the version number in the protocol
+    and interface names and resetting the interface version. Once the protocol
+    is to be declared stable, the 'z' prefix and the version number in the
+    protocol and interface names are removed and the interface version number is
+    reset.
+  </description>
+
+  <interface name="zcr_remote_shell_v2" version="1">
+    <description summary="remote_shell">
+      The global interface that allows clients to turn a wl_surface into a
+      "real window" which is remotely managed but can be stacked, activated
+      and made fullscreen by the user.
+    </description>
+
+    <enum name="error">
+      <entry name="role" value="0" summary="given wl_surface has another role"/>
+      <entry name="invalid_notification_key" value="1" summary="invalid notification key"/>
+    </enum>
+
+    <request name="destroy" type="destructor">
+      <description summary="destroy remote_shell">
+	Destroy this remote_shell object.
+
+	Destroying a bound remote_shell object while there are surfaces
+	still alive created by this remote_shell object instance is illegal
+	and will result in a protocol error.
+      </description>
+    </request>
+
+    <enum name="container">
+      <description summary="containers for remote surfaces">
+	Determine how a remote surface should be stacked relative to other
+	shell surfaces.
+      </description>
+      <entry name="default" value="1" summary="default container"/>
+      <entry name="overlay" value="2" summary="system modal container"/>
+    </enum>
+
+    <request name="get_remote_surface">
+      <description summary="create a remote shell surface from a surface">
+	This creates an remote_surface for the given surface and gives it the
+	remote_surface role. A wl_surface can only be given a remote_surface
+	role once. If get_remote_surface is called with a wl_surface that
+	already has an active remote_surface associated with it, or if it had
+	any other role, an error is raised.
+
+	See the documentation of remote_surface for more details about what an
+	remote_surface is and how it is used.
+      </description>
+      <arg name="id" type="new_id" interface="zcr_remote_surface_v2"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="container" type="uint" enum="container"/>
+    </request>
+
+    <request name="get_notification_surface">
+      <description summary="create a notification surface from a surface">
+	Creates a notification_surface for the given surface, gives it the
+	notification_surface role and associated it with a notification id.
+      </description>
+      <arg name="id" type="new_id" interface="zcr_notification_surface_v2"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="notification_key" type="string"/>
+    </request>
+
+    <event name="default_device_scale_factor" since="1">
+      <description summary="initialize scale configuration">
+	Sends the default device scale factor.
+      </description>
+      <arg name="scale" type="int" summary="DP to pixels ratio, in 8.24 fixed point format"/>
+    </event>
+
+    <request name="get_input_method_surface" since="1">
+      <description summary="Create a input method surface from a surface">
+	Creates an input_method_surface for the given surface, gives it
+	the input_method_surface role.
+      </description>
+      <arg name="id" type="new_id" interface="zcr_input_method_surface_v2"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+
+    <request name="get_toast_surface" since="1">
+      <description summary="Create a toast surface from a surface">
+	Creates an toast_surface for the given surface, gives it
+	the toast_surface role.
+      </description>
+      <arg name="id" type="new_id" interface="zcr_toast_surface_v2"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </request>
+
+    <enum name="layout_mode">
+      <description summary="the layout mode">
+	Determine how a client should layout surfaces.
+      </description>
+      <entry name="windowed" value="1" summary="multiple windows"/>
+      <entry name="tablet" value="2" summary="restricted mode for tablet"/>
+    </enum>
+
+    <event name="layout_mode" since="1">
+      <description summary="sends the layout_mode">
+	Sends the layout_mode used by the server.
+      </description>
+      <arg name="layout_mode" type="uint" enum="layout_mode"/>
+    </event>
+
+    <request name="get_remote_output" since="1">
+      <description summary="extend output interface for remote shell">
+	Instantiate an interface extension for the given wl_output to
+	provide remote shell functionality.
+      </description>
+      <arg name="id" type="new_id" interface="zcr_remote_output_v2" summary="the new remote output interface id"/>
+      <arg name="output" type="object" interface="wl_output"/>
+    </request>
+
+    <enum name="desktop_focus_state">
+      <description summary="desktop foucs state">
+	Desktop client window focus state.
+      </description>
+      <entry name="no_focus" value="1" summary="no window get focused"/>
+      <entry name="client_focused" value="2" summary="client window get focused"/>
+      <entry name="other_client_focused" value="3" summary="other client window get focused"/>
+    </enum>
+
+    <event name="desktop_focus_state_changed" since="1">
+      <description summary="desktop window focus state change">
+	Notifies client that the window focus state change.
+      </description>
+      <arg name="focus_state" type="uint" enum="desktop_focus_state"/>
+    </event>
+
+  </interface>
+
+  <interface name="zcr_remote_surface_v2" version="1">
+    <description summary="A desktop window">
+      An interface that may be implemented by a wl_surface, for
+      implementations that provide a desktop-style user interface
+      and allows for remotely managed windows.
+
+      It provides requests to treat surfaces like windows, allowing to set
+      properties like app id and geometry.
+
+      The client must call wl_surface.commit on the corresponding wl_surface
+      for the remote_surface state to take effect.
+
+      For a surface to be mapped by the compositor the client must have
+      committed both an remote_surface state and a buffer.
+    </description>
+
+    <enum name="systemui_visibility_state">
+      <description summary="systemui visibility behavior">
+	Determine the visibility behavior of the system UI.
+      </description>
+      <entry name="visible" value="1" summary="system ui is visible"/>
+      <entry name="autohide_non_sticky" value="2" summary="system ui autohides and is not sticky"/>
+      <entry name="autohide_sticky" value="3" summary="system ui autohides and is sticky"/>
+    </enum>
+
+    <request name="destroy" type="destructor">
+      <description summary="Destroy the remote_surface">
+	Unmap and destroy the window. The window will be effectively
+	hidden from the user's point of view, and all state will be lost.
+      </description>
+    </request>
+
+    <request name="set_app_id">
+      <description summary="set application ID">
+	Set an application identifier for the surface.
+      </description>
+      <arg name="app_id" type="string"/>
+    </request>
+
+    <request name="set_title">
+      <description summary="set surface title">
+	Set a short title for the surface.
+
+	This string may be used to identify the surface in a task bar,
+	window list, or other user interface elements provided by the
+	compositor.
+
+	The string must be encoded in UTF-8.
+      </description>
+      <arg name="title" type="string"/>
+    </request>
+
+    <request name="set_top_inset">
+      <description summary="set top inset for surface">
+	Set distance from the top of the surface to the contents.
+
+	This distance typically represents the size of the window caption.
+      </description>
+      <arg name="height" type="int"/>
+    </request>
+
+    <request name="maximize">
+      <description summary="maximize">
+	Request that surface is maximized. The window geometry will be updated
+	to whatever the compositor finds appropriate for a maximized window.
+
+	This is only a request that the window should be maximized. The
+	compositor may choose to ignore this request. The client should
+	listen to state_type_changed events to determine if the window was
+	maximized or not.
+      </description>
+    </request>
+
+    <request name="minimize">
+      <description summary="minimize">
+	Request that surface is minimized.
+
+	This is only a request that the window should be minimized. The
+	compositor may choose to ignore this request. The client should
+	listen to state_type_changed events to determine if the window was
+	minimized or not.
+      </description>
+    </request>
+
+    <request name="restore">
+      <description summary="restore">
+	Request that surface is restored. This restores the window geometry
+	to what it was before the window was minimized, maximized or made
+	fullscreen.
+
+	This is only a request that the window should be restored. The
+	compositor may choose to ignore this request. The client should
+	listen to state_type_changed events to determine if the window was restored
+  or not.
+      </description>
+    </request>
+
+    <request name="fullscreen">
+      <description summary="fullscreen">
+	Request that surface is made fullscreen.
+
+	This is only a request that the window should be made fullscreen.
+	The compositor may choose to ignore this request. The client should
+	listen to set_fullscreen events to determine if the window was
+	made fullscreen or not.
+      </description>
+    </request>
+
+    <request name="pin">
+      <description summary="pin">
+	Request that surface is pinned.
+
+	This is only a request that the window should be pinned.
+	The compositor may choose to ignore this request. The client should
+	listen to state_type_changed events to determine if the window was
+	pinned or not. If trusted flag is non-zero, the app can prevent users
+	from exiting the pinned mode.
+      </description>
+      <arg name="trusted" type="int"/>
+    </request>
+
+    <request name="unpin">
+      <description summary="unpin">
+	Request that surface is unpinned.
+
+	This is only a request that the window should be unpinned.
+	The compositor may choose to ignore this request. The client should
+	listen to state_type_changed events to determine if the window was
+	unpinned or not.
+      </description>
+    </request>
+
+    <request name="set_system_modal">
+      <description summary="suggests a re-layout of remote shell input area">
+	Suggests a surface should become system modal.
+      </description>
+    </request>
+
+    <request name="unset_system_modal">
+      <description summary="suggests a re-layout of remote shell input area">
+	Suggests a surface should become non system modal.
+      </description>
+    </request>
+
+    <event name="close">
+      <description summary="surface wants to be closed">
+	The close event is sent by the compositor when the user
+	wants the surface to be closed. This should be equivalent to
+	the user clicking the close button in client-side decorations,
+	if your application has any...
+
+	This is only a request that the user intends to close your
+	window. The client may choose to ignore this request, or show
+	a dialog to ask the user to save their data...
+      </description>
+    </event>
+
+    <enum name="state_type">
+      <description summary="state types for remote surfaces">
+	Defines common show states for shell surfaces.
+      </description>
+      <entry name="normal" value="1" summary="normal window state"/>
+      <entry name="minimized" value="2" summary="minimized window state"/>
+      <entry name="maximized" value="3" summary="maximized window state"/>
+      <entry name="fullscreen" value="4" summary="fullscreen window state"/>
+      <entry name="pinned" value="5" summary="pinned window state"/>
+      <entry name="trusted_pinned" value="6" summary="trusted pinned window state"/>
+      <entry name="moving" value="7" summary="moving window state"/>
+      <entry name="resizing" value="8" summary="resizing window state"/>
+      <entry name="left_snapped" value="9" summary="left snapped window state"/>
+      <entry name="right_snapped" value="10" summary="right snapped window state"/>
+      <entry name="pip" value="11" summary="pip window state"/>
+    </enum>
+
+    <event name="state_type_changed">
+      <description summary="surface state type changed">
+	The state_type_changed event is sent by the compositor when
+	the surface state changed.
+
+	This is an event to notify that the window state changed in compositor.
+	The state change may be triggered by a client's request, or some user
+	action directly handled by the compositor. The client may choose to
+	ignore this event.
+      </description>
+      <arg name="state_type" type="uint" enum="state_type"/>
+    </event>
+
+    <request name="set_rectangular_surface_shadow" since="1">
+      <description summary="set a rectangular shadow">
+	Request that surface needs a rectangular shadow.
+
+	This is only a request that the surface should have a rectangular
+	shadow. The compositor may choose to ignore this request.
+
+	The arguments are given in the remote surface coordinate space and
+	specifies inner bounds of the shadow. Specifying zero width and height
+	will disable the shadow.
+      </description>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+
+    <request name="set_systemui_visibility" since="1">
+      <description summary="requests the system ui visibility behavior for the surface">
+	Requests how the surface will change the visibility of the system UI when it is made active.
+      </description>
+      <arg name="visibility" type="uint" enum="systemui_visibility_state"/>
+    </request>
+
+    <request name="set_always_on_top" since="1">
+      <description summary="set always on top">
+	Request that surface is made to be always on top.
+
+	This is only a request that the window should be always on top.
+	The compositor may choose to ignore this request.
+
+      </description>
+    </request>
+
+    <request name="unset_always_on_top" since="1">
+      <description summary="unset always on top">
+	Request that surface is made to be not always on top.
+
+	This is only a request that the window should be not always on top.
+	The compositor may choose to ignore this request.
+      </description>
+    </request>
+
+    <enum name="orientation">
+      <description summary="window orientation">
+	The orientation of the window.
+      </description>
+      <entry name="portrait" value="1" summary="portrait"/>
+      <entry name="landscape" value="2" summary="landscape"/>
+    </enum>
+
+    <request name="set_orientation" since="1">
+      <description summary="set orientation">
+	Set an orientation for the surface.
+      </description>
+      <arg name="orientation" type="int" enum="orientation"/>
+    </request>
+
+    <event name="window_geometry_changed" since="1">
+      <description summary="announce window geometry commit">
+	Notify the client of committed window geometry.
+
+	The compositor sends this event when it commits window geometry. The
+	client may use this information to convert coordinates of input events
+	using the latest committed geometry.
+      </description>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </event>
+
+    <enum name="bounds_change_reason">
+      <description summary="bounds_change_reason">
+	Specifies the cause of the window bounds change event.
+      </description>
+      <entry name="drag_move" value="1" summary="the window is being moved by drag operation"/>
+      <entry name="drag_resize" value="2" summary="the window is being resized by drag operation."/>
+      <entry name="snap_to_left" value="3" summary="the window is resized to left snapped state"/>
+      <entry name="snap_to_right" value="4" summary="the window is resized to right snapped state"/>
+      <entry name="move" value="5" summary="the window bounds is moved due to other WM operations"/>
+      <entry name="resize" value="6" summary="the window bounds is reiszed due to other WM operations"/>
+      <entry name="pip" value="7" summary="the window bounds is resized or moved for PIP"/>
+    </enum>
+
+    <event name="bounds_changed" since="1">
+      <description summary="The compositor requested to change the bounds">
+	The compositor requested to change its
+	bounds. "bounds_change_reason" specifies the cause of the
+	bounds change. The client may apply the different move/resize
+	strategy depending on the reason.
+
+	"display_id_hi", "display_id_lo" specifies in which workspace
+	the surface should live in.
+
+	The client responds with set_bounds_in_output request, with the
+	bounds it is resized to (this may be different from the bounds
+	requested).
+
+	The client may ignore move request depending on the state,
+	e.g, if it becomes resizable or other constrants.
+      </description>
+      <arg name="display_id_hi" type="uint"/>
+      <arg name="display_id_lo" type="uint"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="bounds_change_reason" type="uint" enum="bounds_change_reason"/>
+    </event>
+
+    <request name="start_move" since="1">
+      <description summary="start an interactive move">
+	Request an interactive, user-driven move of the surface. "x"
+	and "y" specifies the starting point of the pointer device
+	that initiated the move.
+
+	The compositor responds to this request with a drag_started
+	event with "none" direction.  Please see drag_started event
+	for more details.
+
+	The compositor may ignore move requests depending on the state of the
+	surface, e.g. fullscreen or maximized.
+      </description>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+    </request>
+
+    <enum name="resize_direction">
+      <description summary="resize direction">
+	The resize direction for drag operation
+      </description>
+      <entry name="none" value="0" summary="move only, no resize"/>
+      <entry name="left" value="1" summary="resize to the left"/>
+      <entry name="topleft" value="2" summary="resize to the top left"/>
+      <entry name="top" value="3" summary="resize to the top"/>
+      <entry name="topright" value="4" summary="resize to the top right"/>
+      <entry name="right" value="5" summary="resize to the right"/>
+      <entry name="bottomright" value="6" summary="resize to the buttom right"/>
+      <entry name="bottom" value="7" summary="resize to the bottom"/>
+      <entry name="bottomleft" value="8" summary="resize to the bottom left"/>
+    </enum>
+
+    <event name="drag_started" since="1">
+      <description summary="Notifies that a drag to move/resize started.">
+	Notifies a client that the compositor started drag
+	operation. "direction" specifies which direction it is being
+	resized. "none" direction means just move but not resize.
+
+	This will be followed by series of the "bounds_changed" event
+	with "drag_resize" or "drag_move" reasons to update the window
+	bounds druing the drag operation.
+      </description>
+      <arg name="direction" type="uint" enum="resize_direction"/>
+    </event>
+
+    <event name="drag_finished" since="1">
+      <description summary="Notifies that a drag operation has finished.">
+	Called when the drag operation is finished.  "x" and "y"
+	specifies the position of the pointer device used to drag.
+	"canceled" is true if the drag operation is aborted during
+	drag (e.g. by capture change or user action.)
+      </description>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="canceled" type="int" summary="true if the operation was canceled"/>
+    </event>
+
+    <request name="set_can_maximize" since="1">
+      <description summary="set can_maximize">
+	Request that surface can be in maximzied state.
+      </description>
+    </request>
+
+    <request name="unset_can_maximize" since="1">
+      <description summary="unset can_maximize">
+	Request that surface can not be in maximzied state.
+      </description>
+    </request>
+
+    <request name="set_min_size" since="1">
+      <description summary="set the minimum size">
+	Set a minimum size of the surface.
+
+	Values set in this way are double-buffered. They will get
+	applied on the next commit.
+      </description>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+
+    <request name="set_max_size" since="1">
+      <description summary="set the maximum size">
+	Set a maximum size of the surface.
+
+	Values set in this way are double-buffered. They will get
+	applied on the next commit.
+
+	Setting the same size as minimum size makes the surface
+	unresizable.
+      </description>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+
+    <request name="set_snapped_to_left" since="1">
+      <description summary="set the surface to left snapped">
+	Request that surface is snapped to left.
+      </description>
+    </request>
+
+    <request name="set_snapped_to_right" since="1">
+      <description summary="set the surface to right snapped">
+	Request that surface is snapped to right.
+      </description>
+    </request>
+
+    <request name="start_resize" since="1">
+      <description summary="start an interactive resize">
+	Request to start an interactive, user-driven resize of the surface.
+	"x" and "y" specifies the starting point of the pointer device
+	that initiated the reize.
+
+	The compositor responds to this request with a "drag_started"
+	event, followed by "bounds_changed" events, and ends the
+	resize operation with a "drag_finhsed" event. The compositor
+	determines the new bounds using the resize_direction and the
+	pointer event location.
+
+	The compositor may ignore resize requests depending on the state of the
+	surface, e.g. fullscreen or maximized, or no drag event is in pregress.
+      </description>
+      <arg name="resize_direction" type="uint" enum="resize_direction"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+    </request>
+
+    <enum name="frame_type">
+      <description summary="frame types">
+	Frame type that can be used to decorate a surface.
+      </description>
+      <entry name="none" value="0" summary="no frame"/>
+      <entry name="normal" value="1" summary="caption with shadow"/>
+      <entry name="shadow" value="2" summary="shadow only"/>
+      <entry name="autohide" value="3" summary="autohide frame with shadow"/>
+      <entry name="overlay" value="4" summary="overlay frame with shadow"/>
+    </enum>
+
+    <request name="set_frame" since="1">
+      <description summary="request a frame for surface">
+	Enables compositor side frame decoration. |type|
+	specifies the type of frame to use for the surface.
+      </description>
+      <arg name="type" type="uint" enum="frame_type"/>
+    </request>
+
+    <enum name="frame_button_type" bitfield="true">
+      <description summary="frame button types">
+	The mask that represents buttons on frame.
+      </description>
+      <entry name="back" value="1" summary="a button to naviate backwards"/>
+      <entry name="minimize" value="2" summary="a button to minimize the window"/>
+      <entry name="maximize_restore" value="4"
+	     summary="a button to maximize or restore"/>
+      <entry name="menu" value="8"
+	     summary="a button to activate application's menu"/>
+      <entry name="close" value="16" summary="a button to close the window"/>
+      <entry name="zoom" value="32"
+	     summary="a mask to turn the maximize_restore button to zoom button"/>
+      <entry name="center" value="64"
+	     summary="a customizable, center-aligned button"/>
+    </enum>
+
+    <request name="set_frame_buttons" since="1">
+      <description summary="updates buttons' state on frame">
+	Updates the frame's button state. |visible_buttons| and |enabled_buttons|
+	are the union of button mask defined in |frame_button_type| enum.
+
+	The mask present in |enabled_buttons| but not in |visible_buttons| will
+	be ignored.
+      </description>
+      <arg name="visible_buttons" type="uint"/>
+      <arg name="enabled_buttons" type="uint"/>
+    </request>
+
+    <request name="set_extra_title" since="1">
+      <description summary="set extra title string">
+	The extra informational string about the surface. This can be
+	used to show the debug information in the title bar, or log
+	messages.
+
+	This is different from "set_title" which is used to identify
+	the surface.
+
+	The string must be encoded in UTF-8.
+      </description>
+      <arg name="extra_title" type="string"/>
+    </request>
+
+    <enum name="orientation_lock">
+      <description summary="orientation lock request for remote surfaces">
+	Defines orientation request when a remote surface is in foreground.
+      </description>
+      <entry name="none" value="1" summary="no orientation lock"/>
+      <entry name="portrait" value="2" summary="primary or secondary portrait"/>
+      <entry name="landscape" value="3" summary="primary or secondary landscape"/>
+      <entry name="current" value="4" summary="keep current orientation"/>
+      <entry name="portrait_primary" value="5" summary="primary portrait"/>
+      <entry name="landscape_primary" value="6" summary="primary landscape"/>
+      <entry name="portrait_secondary" value="7" summary="secondary portrait"/>
+      <entry name="landscape_secondary" value="8" summary="secondary landscape"/>
+    </enum>
+
+    <request name="set_orientation_lock" since="1">
+      <description summary="set orientation lock for a remote surface">
+	Request a specific orientation behavior when this surface is in foreground.
+      </description>
+      <arg name="orientation_lock" type="uint" enum="orientation_lock"/>
+    </request>
+
+    <request name="pip" since="1">
+      <description summary="set pip for a remote surface">
+	Request that surface is set to Picture-in-Picture (PIP).
+      </description>
+    </request>
+
+    <request name="set_aspect_ratio" since="1">
+      <description summary="set the maximum size">
+	Set an aspect ratio of the surface.
+
+	Values set in this way are double-buffered. They will get
+	applied on the next commit.
+
+	The ratio of the values is used for the ratio of width to height of the
+  surface. The size of surface is restricted to the ratio. If any value is
+  zero, the restriction on aspect ratio is unset.
+      </description>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+
+    <enum name="zoom_change">
+      <description summary="zoom level change">
+	Zoom level change.
+      </description>
+      <entry name="in" value="0" summary="zoom in"/>
+      <entry name="out" value="1" summary="zoom out"/>
+      <entry name="reset" value="2" summary="reset zoom level"/>
+    </enum>
+
+    <event name="change_zoom_level" since="1">
+      <description summary="change zoom level">
+	Request application zoom level change.
+      </description>
+      <arg name="change" type="int" enum="zoom_change"/>
+    </event>
+
+    <request name="set_accessibility_id" since="1">
+      <description summary="set accessibility ID to the surface">
+        Set accessibility window ID to the surface. A negative number removes
+        the existing accessibility ID from the surface.
+      </description>
+      <arg name="id" type="int" summary="Accessibility ID. Negative number removes existing accessibility ID from the surface."/>
+    </request>
+
+    <request name="set_pip_original_window" since="1">
+      <description summary="set the pip original window">
+        Set this surface the original window for the current PIP window.
+      </description>
+    </request>
+
+    <request name="unset_pip_original_window" since="1">
+      <description summary="unset the pip original window">
+        Unset this surface the original window for the current PIP window.
+      </description>
+    </request>
+
+    <request name="set_system_gesture_exclusion" since="1">
+      <description summary="set system gesture exclusion">
+        Set system gesture exclusion region in which system gestures e.g. back
+        gesture should not be triggered.
+      </description>
+      <arg name="region" type="object" interface="wl_region" allow-null="true"/>
+    </request>
+
+    <request name="set_resize_lock" since="1">
+      <description summary="set resize lock state">
+          Enable the resize lock and put restrictions related to resizing on
+          the shell surface.
+
+          The resize lock state is double buffered, and will be applied at the
+          time wl_surface.commit of the corresponding wl_surface is called.
+      </description>
+    </request>
+
+    <request name="unset_resize_lock" since="1">
+      <description summary="unset resize lock state">
+          Disable the resize lock and allow the shell surface to be resized
+          freely.
+
+          The resize lock state is double buffered, and will be applied at the
+          time wl_surface.commit of the corresponding wl_surface is called.
+      </description>
+    </request>
+
+    <event name="bounds_changed_in_output" since="1">
+      <description summary="The compositor requested to change the bounds">
+	The compositor requested to change its
+	bounds. "bounds_change_reason" specifies the cause of the
+	bounds change. The client may apply the different move/resize
+	strategy depending on the reason.
+
+	The "output" specifies the wayland output in which the suface should live.
+
+	The client responds with set_bounds_in_output request, with the
+	bounds it is resized to (this may be different from the bounds
+	requested).
+
+	The client may ignore move request depending on the state,
+	e.g, if it becomes resizable or other constrants.
+      </description>
+      <arg name="output" type="object" interface="wl_output"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+      <arg name="bounds_change_reason" type="uint" enum="bounds_change_reason"/>
+    </event>
+
+    <request name="set_bounds_in_output" since="1">
+      <description summary="set window bounds">
+	Set the "visible bounds" of a window from the user's perspective.
+	Client-side decorations often have invisible portions like drop shadows
+	which should be ignored for the purposes of aligning, placing and
+	constraining windows.
+
+	The bounds are double buffered, and will be applied at the
+	time wl_surface.commit of the corresponding wl_surface is called.
+
+	Once the bounds are set, it is not possible to unset them, and they will
+	remain the same until set_bounds_in_output is called again, even if a new sub-
+	surface or buffer is attached.
+
+	If never set, the value is the surface content bounds. This updates
+	dynamically on every commit.
+
+	The bounds are relative to the given display. If the display is invalid,
+	they are assumed to be relative to the primary display.
+
+	The width and height must be greater than zero.
+      </description>
+      <arg name="output" type="object" interface="wl_output"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+  </interface>
+
+  <interface name="zcr_notification_surface_v2" version="1">
+    <description summary="A notification window">
+      An interface that may be implemented by a wl_surface to host
+      notification contents.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="Destroy the notification_surface">
+	Unmap and destroy the notification surface.
+      </description>
+    </request>
+
+    <request name="set_app_id" since="1">
+      <description summary="set application ID">
+	Set an application identifier for the notification surface.
+      </description>
+      <arg name="app_id" type="string"/>
+    </request>
+  </interface>
+
+  <interface name="zcr_input_method_surface_v2" version="1">
+    <description summary="An input method window">
+      An interface that may be implemented by a wl_surface to host IME contents.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="Destroy the ime_surface">
+	Unmap and destroy the input mtehod surface.
+      </description>
+    </request>
+
+    <request name="set_bounds_in_output" since="1">
+      <description summary="set window bounds">
+	Set the "visible bounds" of a window from the user's perspective.
+
+	The bounds are double buffered, and will be applied at the
+	time wl_surface.commit of the corresponding wl_surface is called.
+
+	Once the bounds are set, it is not possible to unset them, and they will
+	remain the same until set_bounds_in_output is called again, even if a new sub-
+	surface or buffer is attached.
+
+	If never set, the value is the surface content bounds. This updates
+	dynamically on every commit.
+
+	The bounds are relative to the given display. If the display is invalid,
+	they are assumed to be relative to the primary display.
+
+	The width and height must be greater than zero.
+      </description>
+      <arg name="output" type="object" interface="wl_output"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+  </interface>
+
+  <interface name="zcr_toast_surface_v2" version="1">
+    <description summary="A toast window">
+      An interface that may be implemented by a wl_surface to host
+      toast contents.
+    </description>
+
+    <request name="destroy" type="destructor">
+      <description summary="Destroy the toast_surface">
+	Unmap and destroy the toast surface.
+      </description>
+    </request>
+
+    <request name="set_bounds_in_output" since="1">
+      <description summary="set toast bounds position">
+	Set the bounds of a toast window from the user's perspective.
+
+	The bounds are double buffered, and will be applied at the
+	time wl_surface.commit of the corresponding wl_surface is called.
+
+	Once the bounds are set, it is not possible to unset them, and they will
+	remain the same until set_bounds is called again, even if a new sub-
+	surface or buffer is attached.
+
+	If never set, the compositor will determine the toast position.
+
+	The bounds are relative to the given display. If the display is invalid,
+	they are assumed to be relative to the primary display.
+      </description>
+      <arg name="output" type="object" interface="wl_output"/>
+      <arg name="x" type="int"/>
+      <arg name="y" type="int"/>
+      <arg name="width" type="int"/>
+      <arg name="height" type="int"/>
+    </request>
+  </interface>
+
+  <interface name="zcr_remote_output_v2" version="1">
+    <description summary="remote shell interface to a wl_output">
+	An additional interface to a wl_output object, which allows the
+	client to access additional functionality for output.
+    </description>
+
+    <request name="destroy" type="destructor" since="1">
+      <description summary="destroy remote_output">
+	Destroy this remote_output object.
+      </description>
+    </request>
+
+    <event name="display_id" since="1">
+      <description summary="the identifier for the display">
+	[Deprecated] Sends the display identifier used by the server for the display.
+      </description>
+      <arg name="display_id_hi" type="uint"/>
+      <arg name="display_id_lo" type="uint"/>
+    </event>
+
+    <event name="port" since="1">
+      <description summary="the port of the display">
+	Sends the port to which the display is connected for the server.
+      </description>
+      <arg name="port" type="uint"/>
+    </event>
+
+    <event name="identification_data" since="1">
+      <description summary="the identification data for the display">
+	Sends the identification data for the display, typically in the EDID format.
+      </description>
+      <arg name="identification_data" type="array"/>
+    </event>
+
+    <event name="insets" since="1">
+      <description summary="insets for the display in pixels">
+	Sends inset information about a particular display in the display's native coordinates.
+      </description>
+      <arg name="inset_left" type="int"/>
+      <arg name="inset_top" type="int"/>
+      <arg name="inset_right" type="int"/>
+      <arg name="inset_bottom" type="int"/>
+    </event>
+
+    <event name="stable_insets" since="1">
+      <description summary="stable insets for a display in pixels">
+	Sends stable inset information about a particular display in the display's native
+	coordinates.
+      </description>
+      <arg name="stable_inset_left" type="int"/>
+      <arg name="stable_inset_top" type="int"/>
+      <arg name="stable_inset_right" type="int"/>
+      <arg name="stable_inset_bottom" type="int"/>
+    </event>
+
+    <enum name="systemui_behavior">
+      <description summary="systemui behavior">
+	Determine the behavior of the system UI.
+      </description>
+      <entry name="visible" value="1" summary="system ui is visible"/>
+      <entry name="hidden" value="2" summary="system ui is autohide or hidden"/>
+    </enum>
+
+    <event name="systemui_behavior" since="1">
+      <description summary="systemui_behavior_state for a display">
+	Sends information about whether the systemui behavior is auto hide.
+	The "systemui_behavior" value is of enum type "systemui_behavior".
+      </description>
+      <arg name="systemui_behavior" type="int" enum="systemui_behavior"/>
+    </event>
+
+ </interface>
+
+</protocol>
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index 2f239fa..594e6ba9 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -578,6 +578,7 @@
       '-DCMAKE_BUILD_TYPE=Release',
       '-DLLVM_ENABLE_ASSERTIONS=%s' % ('OFF' if args.disable_asserts else 'ON'),
       '-DLLVM_ENABLE_PROJECTS=' + projects,
+      '-DLLVM_CHECK_ENABLED_PROJECTS=OFF',
       '-DLLVM_TARGETS_TO_BUILD=' + targets,
       '-DLLVM_ENABLE_PIC=OFF',
       '-DLLVM_ENABLE_UNWIND_TABLES=OFF',
diff --git a/tools/code_coverage/coverage.py b/tools/code_coverage/coverage.py
index 9c519a9..8f57960b 100755
--- a/tools/code_coverage/coverage.py
+++ b/tools/code_coverage/coverage.py
@@ -163,7 +163,8 @@
     LLVM_PROFDATA_PATH = os.path.join(llvm_bin_dir, 'llvm-profdata')
   else:
     subprocess.check_call([
-        'python', 'tools/clang/scripts/update.py', '--package', 'coverage_tools'
+        sys.executable, 'tools/clang/scripts/update.py', '--package',
+        'coverage_tools'
     ])
 
   if coverage_utils.GetHostPlatform() == 'win':
@@ -1050,7 +1051,8 @@
   # is used by coverage bot for initial setup.
   if len(sys.argv) == 1:
     subprocess.check_call([
-        'python', 'tools/clang/scripts/update.py', '--package', 'coverage_tools'
+        sys.executable, 'tools/clang/scripts/update.py', '--package',
+        'coverage_tools'
     ])
     print(__doc__)
     return
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1cbfacf..927cd23 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -20487,6 +20487,9 @@
 </enum>
 
 <enum name="DifferentPrimaryAccounts">
+  <obsolete>
+    No longer used after 2021-05 and the switch to OAuthMultilogin.
+  </obsolete>
   <int value="0" label="Primary Accounts the same"/>
   <int value="1" label="(obsolete) Primary Accounts different"/>
   <int value="2" label="No GAIA account in cookie jar"/>
@@ -51285,6 +51288,7 @@
   <int value="1028817487"
       label="OmniboxOnFocusSuggestionsContextualWeb:disabled"/>
   <int value="1030608602" label="AutofillAssistantProactiveHelp:enabled"/>
+  <int value="1031239808" label="ForceMajorVersion100InUserAgent:disabled"/>
   <int value="1031281564"
       label="DisablePeripheralDataAccessProtection:disabled"/>
   <int value="1033148287" label="NTPShortcuts:disabled"/>
@@ -52635,6 +52639,7 @@
   <int value="2069999572"
       label="AllowSignedHTTPExchangeCertsWithoutExtension:disabled"/>
   <int value="2070207131" label="OpenscreenCastStreamingSession:disabled"/>
+  <int value="2071148245" label="ForceMajorVersion100InUserAgent:enabled"/>
   <int value="2071229145" label="BloatedRendererDetection:enabled"/>
   <int value="2071340353" label="progress-bar-completion"/>
   <int value="2071461362" label="disable-credit-card-scan"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index b72d492..b36be8a 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -2215,7 +2215,7 @@
 </histogram>
 
 <histogram name="Android.Omnibox.UsedSuggestionFromCache" enum="Boolean"
-    expires_after="2021-10-04">
+    expires_after="2022-09-04">
   <owner>ender@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index 9d87c45..390682a3 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1138,7 +1138,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Settings.BlurredWindowDuration" units="ms"
-    expires_after="2021-10-01">
+    expires_after="2022-09-01">
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-customization@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index 58b662e..ecdf6a9 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -16692,6 +16692,9 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="Signin_Reconciler" separator=".">
+  <obsolete>
+    No longer used after 2021-05 and the switch to OAuthMultilogin.
+  </obsolete>
   <suffix name="FirstRun"
       label="First execution of the reconciler after the profile was loaded
              or the new_profile_management flag was toggled."/>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 0f94d0c..9437d48 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -142,7 +142,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.DisableProfile.Result"
-    enum="HermesResponseStatus" expires_after="2021-11-01">
+    enum="HermesResponseStatus" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -155,7 +155,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.EnableProfile.Result"
-    enum="HermesResponseStatus" expires_after="2021-11-01">
+    enum="HermesResponseStatus" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -185,7 +185,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallViaQrCode.OperationResult"
-    enum="NetworkCellularESimInstallViaQrCodeResult" expires_after="2021-11-01">
+    enum="NetworkCellularESimInstallViaQrCodeResult" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -200,7 +200,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.InstallViaQrCode.Result"
-    enum="HermesResponseStatus" expires_after="2022-03-01">
+    enum="HermesResponseStatus" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -264,7 +264,7 @@
 
 <histogram name="Network.Cellular.ESim.RequestPendingProfiles.OperationResult"
     enum="NetworkCellularESimRequestPendingProfilesResult"
-    expires_after="2021-11-01">
+    expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -279,7 +279,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.RequestPendingProfiles.Result"
-    enum="HermesResponseStatus" expires_after="2021-11-01">
+    enum="HermesResponseStatus" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -322,7 +322,7 @@
 
 <histogram name="Network.Cellular.ESim.UninstallProfile.OperationResult"
     enum="NetworkCellularESimUninstallOperationResult"
-    expires_after="2021-11-01">
+    expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -336,7 +336,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.ESim.UninstallProfile.Result"
-    enum="HermesResponseStatus" expires_after="2021-11-01">
+    enum="HermesResponseStatus" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -357,7 +357,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.InhibitResult"
-    enum="NetworkCellularInhibitResult" expires_after="2021-11-01">
+    enum="NetworkCellularInhibitResult" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -383,7 +383,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PrepareCellularConnection.OperationResult"
-    enum="NetworkCellularPrepareForConnectionResult" expires_after="2021-11-01">
+    enum="NetworkCellularPrepareForConnectionResult" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>khorimoto@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
@@ -397,7 +397,7 @@
 </histogram>
 
 <histogram name="Network.Cellular.PSim.OtaActivationResult"
-    enum="NetworkCellularPSimActivationResult" expires_after="2021-11-01">
+    enum="NetworkCellularPSimActivationResult" expires_after="2022-09-01">
   <owner>azeemarshad@chromium.org</owner>
   <owner>cros-connectivity@google.com</owner>
   <owner>hsuregan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 7b6feb2..47af2ad 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -236,7 +236,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.Ads.HeavyAds.DisallowedByBlocklist"
-    enum="BooleanBlocked" expires_after="2021-10-04">
+    enum="BooleanBlocked" expires_after="2022-10-04">
   <owner>johnidel@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -1774,7 +1774,7 @@
 </histogram>
 
 <histogram name="PageLoad.FrameCounts.AdFrames.PerFrame.UserActivation"
-    enum="AdUserActivationStatus" expires_after="2021-10-01">
+    enum="AdUserActivationStatus" expires_after="2022-10-01">
   <owner>johnidel@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -1790,7 +1790,7 @@
 </histogram>
 
 <histogram name="PageLoad.FrameCounts.AdFrames.Total" units="Ad frames"
-    expires_after="2021-10-01">
+    expires_after="2022-10-01">
   <owner>jkarlin@chromium.org</owner>
   <owner>johnidel@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index 4d1336b8..26b9ce3 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -961,8 +961,9 @@
 
 <histogram name="Signin.Reconciler.AddedToCookieJar" units="accounts"
     expires_after="never">
-<!-- expires-never: used to detect and debug signin issues -->
-
+  <obsolete>
+    No longer emitted after 2021-05 and the switch to OAuthMultilogin.
+  </obsolete>
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -986,8 +987,9 @@
 
 <histogram name="Signin.Reconciler.DifferentPrimaryAccounts"
     enum="DifferentPrimaryAccounts" expires_after="never">
-<!-- expires-never: used to detect and debug signin issues -->
-
+  <obsolete>
+    No longer emitted after 2021-05 and the switch to OAuthMultilogin.
+  </obsolete>
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
@@ -1066,8 +1068,9 @@
 
 <histogram name="Signin.Reconciler.RemovedFromCookieJar" units="accounts"
     expires_after="never">
-<!-- expires-never: used to detect and debug signin issues -->
-
+  <obsolete>
+    No longer emitted after 2021-05 and the switch to OAuthMultilogin.
+  </obsolete>
   <owner>msarda@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 1a333d3..48a4973 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1937,7 +1937,7 @@
 </histogram>
 
 <histogram name="Tabs.ScrubbedInInterval.KeyPress" units="tabs"
-    expires_after="2021-10-01">
+    expires_after="2022-02-13">
   <owner>corising@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -1949,7 +1949,7 @@
 </histogram>
 
 <histogram name="Tabs.ScrubbedInInterval.MousePress" units="tabs"
-    expires_after="2021-10-01">
+    expires_after="2022-02-13">
   <owner>corising@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py
index 2958695..e9432ad 100644
--- a/tools/perf/core/bot_platforms.py
+++ b/tools/perf/core/bot_platforms.py
@@ -549,7 +549,7 @@
     ' Intel Kaby Lake HD Graphics 630', _WIN_10_BENCHMARK_CONFIGS,
     26, 'win', executables=_WIN_10_EXECUTABLE_CONFIGS)
 WIN_10_AMD = PerfPlatform('win-10_amd-perf', 'Windows AMD chipset',
-                          _WIN_10_AMD_BENCHMARK_CONFIGS, 2, 'win')
+                          _WIN_10_AMD_BENCHMARK_CONFIGS, 1, 'win')
 WIN_7 = PerfPlatform('Win 7 Perf', 'N/A', _WIN_7_BENCHMARK_CONFIGS, 2, 'win')
 WIN_7_GPU = PerfPlatform('Win 7 Nvidia GPU Perf', 'N/A',
                          _WIN_7_GPU_BENCHMARK_CONFIGS, 3, 'win')
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py
index 0e5fe4a..0674854df 100755
--- a/tools/perf/core/perf_data_generator.py
+++ b/tools/perf/core/perf_data_generator.py
@@ -103,7 +103,7 @@
 
 # This is an opt-in list for builders which uses dynamic sharding.
 DYNAMIC_SHARDING_TESTERS = [
-    'android-pixel2-perf', 'win-10_amd-perf', 'android-pixel2-perf-fyi',
+    'android-pixel2-perf', 'android-pixel2-perf-fyi',
     'android-pixel2-perf-calibration', 'linux-perf-calibration'
 ]
 
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 105cbadb..7236952 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -10,7 +10,7 @@
         },
         "mac": {
             "hash": "4dbd1e0f0627124cb0499e7d85a5e4c6ad27e495",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/62ae508a04c805f323639e434bfeae2ac811b06d/trace_processor_shell"
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/e311098b41b59af1a1bc9d59fc8745bd2b8ebebb/trace_processor_shell"
         },
         "linux_arm64": {
             "hash": "5074025a2898ec41a872e70a5719e417acb0a380",
diff --git a/tools/perf/core/shard_maps/timing_data/win-10_amd-perf_timing.json b/tools/perf/core/shard_maps/timing_data/win-10_amd-perf_timing.json
index 0637a08..ced048c 100644
--- a/tools/perf/core/shard_maps/timing_data/win-10_amd-perf_timing.json
+++ b/tools/perf/core/shard_maps/timing_data/win-10_amd-perf_timing.json
@@ -1 +1,338 @@
-[]
\ No newline at end of file
+[
+    {
+        "duration": "178.0",
+        "name": "jetstream/JetStream"
+    },
+    {
+        "duration": "170.0",
+        "name": "jetstream2/JetStream2"
+    },
+    {
+        "duration": "19.0",
+        "name": "kraken/http://krakenbenchmark.mozilla.org/kraken-1.1/driver.html"
+    },
+    {
+        "duration": "37.0",
+        "name": "octane/Octane"
+    },
+    {
+        "duration": "33.0",
+        "name": "system_health.common_desktop/browse:media:googleplaystore:2021"
+    },
+    {
+        "duration": "74.0",
+        "name": "system_health.common_desktop/browse:media:imgur"
+    },
+    {
+        "duration": "88.0",
+        "name": "system_health.common_desktop/browse:media:pinterest:2018"
+    },
+    {
+        "duration": "58.0",
+        "name": "system_health.common_desktop/browse:media:tumblr:2018"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:media:youtube:2019"
+    },
+    {
+        "duration": "64.0",
+        "name": "system_health.common_desktop/browse:media:youtubetv:2019"
+    },
+    {
+        "duration": "73.0",
+        "name": "system_health.common_desktop/browse:media:youtubetv_watch:2020"
+    },
+    {
+        "duration": "43.0",
+        "name": "system_health.common_desktop/browse:news:cnn:2021"
+    },
+    {
+        "duration": "47.0",
+        "name": "system_health.common_desktop/browse:news:flipboard:2020"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:news:hackernews:2020"
+    },
+    {
+        "duration": "66.0",
+        "name": "system_health.common_desktop/browse:news:nytimes:2020"
+    },
+    {
+        "duration": "57.0",
+        "name": "system_health.common_desktop/browse:news:reddit:2020"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.common_desktop/browse:search:google:2020"
+    },
+    {
+        "duration": "34.0",
+        "name": "system_health.common_desktop/browse:search:google_india:2021"
+    },
+    {
+        "duration": "66.0",
+        "name": "system_health.common_desktop/browse:social:facebook_infinite_scroll:2018"
+    },
+    {
+        "duration": "56.0",
+        "name": "system_health.common_desktop/browse:social:tumblr_infinite_scroll:2018"
+    },
+    {
+        "duration": "49.0",
+        "name": "system_health.common_desktop/browse:social:twitter:2018"
+    },
+    {
+        "duration": "60.0",
+        "name": "system_health.common_desktop/browse:social:twitter_infinite_scroll:2018"
+    },
+    {
+        "duration": "57.0",
+        "name": "system_health.common_desktop/browse:tech:discourse_infinite_scroll:2018"
+    },
+    {
+        "duration": "53.0",
+        "name": "system_health.common_desktop/browse:tools:autocad:2021"
+    },
+    {
+        "duration": "37.0",
+        "name": "system_health.common_desktop/browse:tools:docs_scrolling"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:earth:2020"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:gmail-compose:2020"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:gmail-labelclick:2020"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:gmail-openconversation:2020"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:gmail-search:2020"
+    },
+    {
+        "duration": "69.0",
+        "name": "system_health.common_desktop/browse:tools:maps:2019"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse:tools:sheets:2019"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/browse_accessibility:media:youtube"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.common_desktop/browse_accessibility:tech:codesearch:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:chrome:blank"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:games:alphabetty:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:games:bubbles:2020"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:games:lazors"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:games:miniclip:2018"
+    },
+    {
+        "duration": "23.0",
+        "name": "system_health.common_desktop/load:games:spychase:2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:media:9gag"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:media:dailymotion:2019"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:media:facebook_feed:desktop:2020"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:media:facebook_photos:2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:media:facebook_photos:desktop:2020"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:media:flickr:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:media:google_images:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:media:imgur:2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:media:soundcloud:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:media:youtube:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:media:youtubelivingroom:2020"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:news:bbc:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:news:cnn:2020"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:news:flipboard"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:news:hackernews:2018"
+    },
+    {
+        "duration": "22.0",
+        "name": "system_health.common_desktop/load:news:nytimes:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:news:qq:2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:news:reddit:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:news:wikipedia:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:search:amazon:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:search:baidu:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:search:ebay:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:search:flipkart:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:search:google:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:search:taobao:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:search:yahoo:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:search:yandex:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:social:instagram:2018"
+    },
+    {
+        "duration": "21.0",
+        "name": "system_health.common_desktop/load:social:pinterest:2019"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:social:vk:2018"
+    },
+    {
+        "duration": "28.0",
+        "name": "system_health.common_desktop/load:tools:chat:2020"
+    },
+    {
+        "duration": "73.0",
+        "name": "system_health.common_desktop/load:tools:docs:2019"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load:tools:drive:2019"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/load:tools:gmail:2019"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:tools:stackoverflow:2018"
+    },
+    {
+        "duration": "19.0",
+        "name": "system_health.common_desktop/load:tools:weather:2019"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load_accessibility:media:wikipedia:2018"
+    },
+    {
+        "duration": "20.0",
+        "name": "system_health.common_desktop/load_accessibility:shopping:amazon:2018"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/long_running:tools:gmail-background"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/long_running:tools:gmail-foreground"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/multitab:misc:typical24"
+    },
+    {
+        "duration": "6.0",
+        "name": "system_health.common_desktop/multitab:misc:typical24:2018"
+    },
+    {
+        "duration": "44.0",
+        "name": "system_health.common_desktop/play:media:google_play_music"
+    },
+    {
+        "duration": "44.0",
+        "name": "system_health.common_desktop/play:media:soundcloud:2018"
+    }
+]
\ No newline at end of file
diff --git a/tools/perf/core/shard_maps/win-10_amd-perf_map.json b/tools/perf/core/shard_maps/win-10_amd-perf_map.json
index 8603faa..08faffc 100644
--- a/tools/perf/core/shard_maps/win-10_amd-perf_map.json
+++ b/tools/perf/core/shard_maps/win-10_amd-perf_map.json
@@ -4,6 +4,9 @@
             "jetstream": {
                 "abridged": false
             },
+            "jetstream2": {
+                "abridged": false
+            },
             "kraken": {
                 "abridged": false
             },
@@ -11,29 +14,16 @@
                 "abridged": false
             },
             "system_health.common_desktop": {
-                "end": 39,
-                "abridged": false
-            }
-        }
-    },
-    "1": {
-        "benchmarks": {
-            "jetstream2": {
-                "abridged": false
-            },
-            "system_health.common_desktop": {
-                "begin": 39,
                 "abridged": false
             }
         }
     },
     "extra_infos": {
         "num_stories": 84,
-        "predicted_min_shard_time": 410,
+        "predicted_min_shard_time": 2657.0,
         "predicted_min_shard_index": 0,
-        "predicted_max_shard_time": 410,
+        "predicted_max_shard_time": 2657.0,
         "predicted_max_shard_index": 0,
-        "shard #0": 410,
-        "shard #1": 410
+        "shard #0": 2657.0
     }
 }
\ No newline at end of file
diff --git a/ui/base/clipboard/clipboard.cc b/ui/base/clipboard/clipboard.cc
index 8a26541..80687f1 100644
--- a/ui/base/clipboard/clipboard.cc
+++ b/ui/base/clipboard/clipboard.cc
@@ -13,6 +13,7 @@
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/notreached.h"
+#include "base/strings/utf_string_conversions.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "ui/gfx/geometry/size.h"
 #include "url/gurl.h"
@@ -164,6 +165,34 @@
   return custom_format_names;
 }
 
+std::vector<std::u16string>
+Clipboard::ReadAvailableStandardAndCustomFormatNames(
+    ClipboardBuffer buffer,
+    const DataTransferEndpoint* data_dst) const {
+  DCHECK(CalledOnValidThread());
+  std::vector<std::u16string> format_names;
+  // Native applications generally read formats in order of
+  // fidelity/specificity, reading only the most specific format they support
+  // when possible to save resources. For example, if an image/tiff and
+  // image/jpg were both available on the clipboard, an image editing
+  // application with sophisticated needs may choose the image/tiff payload, due
+  // to it providing an uncompressed image, and only fall back to image/jpg when
+  // the image/tiff is not available. To allow other native applications to read
+  // these most specific formats first, clipboard formats will be ordered as
+  // follows:
+  // 1. Pickled formats, in order of definition in the ClipboardItem.
+  // 2. Sanitized standard formats, ordered as determined by the browser.
+
+  std::map<std::string, std::string> custom_format_names =
+      ExtractCustomPlatformNames(buffer, data_dst);
+  for (const auto& items : custom_format_names)
+    format_names.push_back(base::ASCIIToUTF16(items.first));
+  for (const auto& item : GetStandardFormats(buffer, data_dst)) {
+    format_names.push_back(item);
+  }
+  return format_names;
+}
+
 Clipboard::Clipboard() = default;
 Clipboard::~Clipboard() = default;
 
@@ -296,14 +325,6 @@
   std::move(callback).Run(std::move(types));
 }
 
-void Clipboard::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst,
-    ReadAvailablePlatformSpecificFormatNamesCallback callback) const {
-  std::move(callback).Run(
-      ReadAvailablePlatformSpecificFormatNames(buffer, data_dst));
-}
-
 void Clipboard::ReadText(ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst,
                          ReadTextCallback callback) const {
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index 85009c94..94f509e 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -48,8 +48,6 @@
  public:
   using ReadAvailableTypesCallback =
       base::OnceCallback<void(std::vector<std::u16string> result)>;
-  using ReadAvailablePlatformSpecificFormatNamesCallback =
-      base::OnceCallback<void(std::vector<std::u16string> result)>;
   using ReadTextCallback = base::OnceCallback<void(std::u16string result)>;
   using ReadAsciiTextCallback = base::OnceCallback<void(std::string result)>;
   using ReadHtmlCallback = base::OnceCallback<void(std::u16string markup,
@@ -125,6 +123,18 @@
   virtual const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const = 0;
 
+  // Returns all the standard MIME types that are present on the clipboard.
+  // The standard MIME types are the formats that are well defined by the
+  // Clipboard API
+  // spec(https://w3c.github.io/clipboard-apis/#mandatory-data-types-x).
+  // Currently we support text/html, text/plain, text/rtf, image/png &
+  // text/uri-list.
+  // TODO(snianu): Create a more generalized function for standard formats that
+  // can be shared by all platforms.
+  virtual std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const = 0;
+
   // Tests whether the clipboard contains a certain format.
   virtual bool IsFormatAvailable(
       const ClipboardFormatType& format,
@@ -151,13 +161,6 @@
   virtual void ReadAvailableTypes(ClipboardBuffer buffer,
                                   const DataTransferEndpoint* data_dst,
                                   ReadAvailableTypesCallback callback) const;
-  // Includes all types, including unsanitized types.
-  // Omits formats held within pickles, as they're different from what a native
-  // application would see.
-  virtual void ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst,
-      ReadAvailablePlatformSpecificFormatNamesCallback callback) const;
 
   // Reads Unicode text from the clipboard, if available.
   virtual void ReadText(ClipboardBuffer buffer,
@@ -224,9 +227,6 @@
   virtual void ReadAvailableTypes(ClipboardBuffer buffer,
                                   const DataTransferEndpoint* data_dst,
                                   std::vector<std::u16string>* types) const = 0;
-  virtual std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const = 0;
   virtual void ReadText(ClipboardBuffer buffer,
                         const DataTransferEndpoint* data_dst,
                         std::u16string* result) const = 0;
@@ -275,6 +275,10 @@
       ClipboardBuffer buffer,
       const DataTransferEndpoint* data_dst) const;
 
+  std::vector<std::u16string> ReadAvailableStandardAndCustomFormatNames(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const;
+
  protected:
   // PortableFormat designates the type of data to be stored in the clipboard.
   // This designation is shared across all OSes. The system-specific designation
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc
index e948b14..3f5e6b2 100644
--- a/ui/base/clipboard/clipboard_android.cc
+++ b/ui/base/clipboard/clipboard_android.cc
@@ -585,23 +585,6 @@
 
 // |data_dst| is not used. It's only passed to be consistent with other
 // platforms.
-std::vector<std::u16string>
-ClipboardAndroid::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-  std::vector<ClipboardFormatType> formats = g_map.Get().GetFormats();
-
-  std::vector<std::u16string> types;
-  types.reserve(formats.size());
-  for (const ClipboardFormatType& format : formats)
-    types.push_back(base::UTF8ToUTF16(format.GetName()));
-
-  return types;
-}
-
-// |data_dst| is not used. It's only passed to be consistent with other
-// platforms.
 void ClipboardAndroid::ReadText(ClipboardBuffer buffer,
                                 const DataTransferEndpoint* data_dst,
                                 std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_android.h b/ui/base/clipboard/clipboard_android.h
index 51cbe982..c3f93af5 100644
--- a/ui/base/clipboard/clipboard_android.h
+++ b/ui/base/clipboard/clipboard_android.h
@@ -65,6 +65,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -72,9 +75,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -136,14 +136,6 @@
   void WriteData(const ClipboardFormatType& format,
                  const char* data_data,
                  size_t data_len) override;
-
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
 };
 
 }  // namespace ui
diff --git a/ui/base/clipboard/clipboard_mac.h b/ui/base/clipboard/clipboard_mac.h
index b7fa6dc4..2ea668a 100644
--- a/ui/base/clipboard/clipboard_mac.h
+++ b/ui/base/clipboard/clipboard_mac.h
@@ -45,6 +45,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -54,9 +57,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -122,14 +122,6 @@
   SkBitmap ReadImageInternal(ClipboardBuffer buffer,
                              NSPasteboard* pasteboard) const;
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
-
   // Mapping of OS-provided sequence number to a unique token.
   mutable struct {
     NSInteger sequence_number;
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index e9e9a48..3da086f 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -208,24 +208,6 @@
 
 // |data_dst| is not used. It's only passed to be consistent with other
 // platforms.
-std::vector<std::u16string>
-ClipboardMac::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  DCHECK(CalledOnValidThread());
-  DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
-
-  NSArray* types = [GetPasteboard() types];
-
-  std::vector<std::u16string> type_names;
-  type_names.reserve([types count]);
-  for (NSString* type in types)
-    type_names.push_back(base::SysNSStringToUTF16(type));
-  return type_names;
-}
-
-// |data_dst| is not used. It's only passed to be consistent with other
-// platforms.
 void ClipboardMac::ReadText(ClipboardBuffer buffer,
                             const DataTransferEndpoint* data_dst,
                             std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc
index def1616..445b9ef 100644
--- a/ui/base/clipboard/clipboard_non_backed.cc
+++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -509,21 +509,6 @@
   }
 }
 
-std::vector<std::u16string>
-ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  DCHECK(CalledOnValidThread());
-
-  std::vector<std::u16string> types;
-
-  if (!clipboard_internal_->IsReadAllowed(data_dst))
-    return types;
-
-  // Includes all non-pickled AvailableTypes.
-  return GetStandardFormats(buffer, data_dst);
-}
-
 void ClipboardNonBacked::ReadText(ClipboardBuffer buffer,
                                   const DataTransferEndpoint* data_dst,
                                   std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_non_backed.h b/ui/base/clipboard/clipboard_non_backed.h
index 1ae8bf1..6f96413f 100644
--- a/ui/base/clipboard/clipboard_non_backed.h
+++ b/ui/base/clipboard/clipboard_non_backed.h
@@ -56,6 +56,9 @@
 
   // Clipboard overrides:
   void OnPreShutdown() override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -63,9 +66,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -129,14 +129,6 @@
                  const char* data_data,
                  size_t data_len) override;
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
-
   const std::unique_ptr<ClipboardInternal> clipboard_internal_;
 };
 
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc
index d851b95..384e4a8 100644
--- a/ui/base/clipboard/clipboard_ozone.cc
+++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -400,22 +400,6 @@
 }
 
 // TODO(crbug.com/1103194): |data_dst| should be supported.
-std::vector<std::u16string>
-ClipboardOzone::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  DCHECK(CalledOnValidThread());
-
-  std::vector<std::string> mime_types =
-      async_clipboard_ozone_->RequestMimeTypes(buffer);
-  std::vector<std::u16string> types;
-  types.reserve(mime_types.size());
-  for (auto& mime_type : mime_types)
-    types.push_back(base::UTF8ToUTF16(mime_type));
-  return types;
-}
-
-// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadText(ClipboardBuffer buffer,
                               const DataTransferEndpoint* data_dst,
                               std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_ozone.h b/ui/base/clipboard/clipboard_ozone.h
index f076f24..30dbb90 100644
--- a/ui/base/clipboard/clipboard_ozone.h
+++ b/ui/base/clipboard/clipboard_ozone.h
@@ -31,6 +31,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -38,9 +41,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -106,14 +106,6 @@
 
   std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer) const;
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
-
   class AsyncClipboardOzone;
 
   std::unique_ptr<AsyncClipboardOzone> async_clipboard_ozone_;
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index fb13f39..409af3dc 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -806,8 +806,8 @@
   EXPECT_EQ(payload1, unpickled_string1);
 }
 
-// TODO(crbug.com/106449): Implement custom formats on other platforms.
-#if defined(OS_WIN)
+// TODO(crbug.com/106449): Implement multiple custom format write on Chrome OS.
+#if !BUILDFLAG(IS_CHROMEOS_ASH)
 TYPED_TEST(ClipboardTest, DataTest) {
   const std::string kFormatString = "chromium/x-test-format";
   const std::u16string kFormatString16 = u"chromium/x-test-format";
@@ -857,7 +857,7 @@
   }
 
   // Check format 1.
-  EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+  EXPECT_THAT(this->clipboard().ReadAvailableStandardAndCustomFormatNames(
                   ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(kFormatString116));
   std::string custom_format_json;
@@ -875,7 +875,7 @@
   EXPECT_EQ(payload1, output1);
 
   // Check format 2.
-  EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+  EXPECT_THAT(this->clipboard().ReadAvailableStandardAndCustomFormatNames(
                   ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(kFormatString216));
   EXPECT_TRUE(custom_format_names.find(kFormatString2) !=
@@ -910,7 +910,7 @@
   }
 
   // Check format 1.
-  EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+  EXPECT_THAT(this->clipboard().ReadAvailableStandardAndCustomFormatNames(
                   ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(kFormatString116));
   std::string custom_format_json;
@@ -928,7 +928,7 @@
   EXPECT_EQ(payload1, output1);
 
   // Check format 2.
-  EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
+  EXPECT_THAT(this->clipboard().ReadAvailableStandardAndCustomFormatNames(
                   ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(kFormatString216));
   EXPECT_TRUE(custom_format_names.find(kFormatString2) !=
@@ -939,75 +939,11 @@
                              /* data_dst = */ nullptr, &output2);
   EXPECT_EQ(payload2, output2);
 }
-#endif
-
-// crbug.com/1224904: Flaky on Mac.
-#if defined(OS_MAC)
-#define MAYBE_ReadAvailablePlatformSpecificFormatNamesTest \
-  DISABLED_ReadAvailablePlatformSpecificFormatNamesTest
-#else
-#define MAYBE_ReadAvailablePlatformSpecificFormatNamesTest \
-  ReadAvailablePlatformSpecificFormatNamesTest
-#endif
-TYPED_TEST(ClipboardTest, MAYBE_ReadAvailablePlatformSpecificFormatNamesTest) {
-  // We're testing platform-specific behavior, so use PlatformClipboardTest.
-  // TODO(https://crbug.com/1083050): The template shouldn't know about its
-  // instantiations. Move this information up using a flag, virtual method, or
-  // creating separate test files for different platforms.
-  std::string test_suite_name = ::testing::UnitTest::GetInstance()
-                                    ->current_test_info()
-                                    ->test_suite_name();
-  // TODO(crbug.com/106449): Update other platforms to support custom formats.
-  if (test_suite_name != std::string("ClipboardTest/PlatformClipboardTest"))
-    return;
-
-  std::u16string text = u"Test String";
-  std::string ascii_text;
-  {
-    ScopedClipboardWriter clipboard_writer(ClipboardBuffer::kCopyPaste);
-    // `WriteText` uses `ClipboardFormatType::PlainTextType` format.
-    clipboard_writer.WriteText(text);
-  }
-
-  const std::vector<std::u16string> raw_types =
-      this->clipboard().ReadAvailablePlatformSpecificFormatNames(
-          ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
-#if defined(OS_APPLE)
-  EXPECT_THAT(raw_types, Contains(u"public.utf8-plain-text"));
-  EXPECT_THAT(raw_types, Contains(u"NSStringPboardType"));
-  EXPECT_EQ(raw_types.size(), 2u);
-// TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
-// of lacros-chrome is complete.
-#elif defined(OS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \
-    !BUILDFLAG(IS_CHROMECAST) && !BUILDFLAG(IS_CHROMEOS_LACROS)
-  EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeText)));
-  EXPECT_THAT(raw_types, Contains(u"TEXT"));
-  EXPECT_THAT(raw_types, Contains(u"STRING"));
-  EXPECT_THAT(raw_types, Contains(u"UTF8_STRING"));
-#if defined(USE_OZONE)
-  if (features::IsUsingOzonePlatform()) {
-    EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeTextUtf8)));
-    EXPECT_EQ(raw_types.size(), 5u);
-    return;
-  }
-#endif  // USE_OZONE
-#if defined(USE_X11)
-  EXPECT_FALSE(features::IsUsingOzonePlatform());
-  EXPECT_EQ(raw_types.size(), 4u);
-#endif  // USE_X11
-#elif defined(USE_AURA) || defined(OS_ANDROID) || defined(OS_WIN)
-  EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kMimeTypeText)));
-  EXPECT_EQ(raw_types.size(), 1u);
-#else
-#error Unsupported platform
-#endif
-}
 
 // Test that platform-specific functionality works, with a predefined format in
 // On X11 Linux, this test uses a simple MIME type, text/plain.
 // On Windows, this test uses a pre-defined ANSI format, CF_TEXT, and tests that
 // the Windows implicitly converts this to UNICODE as expected.
-#if defined(OS_WIN) || defined(USE_X11)
 TYPED_TEST(ClipboardTest, PlatformSpecificDataTest) {
   // We're testing platform-specific behavior, so use PlatformClipboardTest.
   // TODO(https://crbug.com/1083050): The template shouldn't know about its
@@ -1024,7 +960,7 @@
 #if defined(OS_WIN)
   // Windows requires an extra '\0' at the end for a raw write.
   const std::string kPlatformSpecificText = text + '\0';
-#elif defined(USE_X11)
+#else
   const std::string kPlatformSpecificText = text;
 #endif
   base::span<const uint8_t> text_span(
@@ -1052,7 +988,7 @@
                              &platform_specific_result);
   EXPECT_EQ(platform_specific_result, kPlatformSpecificText);
 }
-#endif  // defined(OS_WIN) || defined(USE_X11)
+#endif
 
 #if !defined(OS_APPLE) && !defined(OS_ANDROID)
 TYPED_TEST(ClipboardTest, HyperlinkTest) {
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index 68c758d..8d6950b 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -332,29 +332,6 @@
 
 // |data_dst| is not used. It's only passed to be consistent with other
 // platforms.
-std::vector<std::u16string>
-ClipboardWin::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  int count = ::CountClipboardFormats();
-  if (!count)
-    return {};
-
-  std::vector<std::u16string> types;
-  types.reserve(count);
-
-  // Check if we have any custom formats in the clipboard.
-  std::map<std::string, std::string> custom_format_names =
-      ExtractCustomPlatformNames(buffer, data_dst);
-  for (const auto& item : custom_format_names)
-    types.push_back(base::ASCIIToUTF16(item.first));
-  for (const auto& item : GetStandardFormats(buffer, data_dst))
-    types.push_back(item);
-  return types;
-}
-
-// |data_dst| is not used. It's only passed to be consistent with other
-// platforms.
 void ClipboardWin::ReadText(ClipboardBuffer buffer,
                             const DataTransferEndpoint* data_dst,
                             std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_win.h b/ui/base/clipboard/clipboard_win.h
index efde01e..4c64c82 100644
--- a/ui/base/clipboard/clipboard_win.h
+++ b/ui/base/clipboard/clipboard_win.h
@@ -40,6 +40,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -47,9 +50,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -120,16 +120,6 @@
   // if necessary.  Marked const for lazily initialization by const methods.
   HWND GetClipboardWindow() const;
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  // TODO(snianu): Create a more generalized function for standard formats that
-  // can be shared by all platforms.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
-
   // Mark this as mutable so const methods can still do lazy initialization.
   mutable std::unique_ptr<base::win::MessageWindow> clipboard_owner_;
 
diff --git a/ui/base/clipboard/clipboard_x11.cc b/ui/base/clipboard/clipboard_x11.cc
index 764fb12..d75c520b 100644
--- a/ui/base/clipboard/clipboard_x11.cc
+++ b/ui/base/clipboard/clipboard_x11.cc
@@ -129,19 +129,6 @@
 
 // |data_dst| is not used. It's only passed to be consistent with other
 // platforms.
-std::vector<std::u16string>
-ClipboardX11::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const DataTransferEndpoint* data_dst) const {
-  DCHECK(CalledOnValidThread());
-  std::vector<std::u16string> format_names;
-  for (const auto& name : x_clipboard_helper_->GetAvailableAtomNames(buffer))
-    format_names.push_back(base::UTF8ToUTF16(name));
-  return format_names;
-}
-
-// |data_dst| is not used. It's only passed to be consistent with other
-// platforms.
 void ClipboardX11::ReadText(ClipboardBuffer buffer,
                             const DataTransferEndpoint* data_dst,
                             std::u16string* result) const {
diff --git a/ui/base/clipboard/clipboard_x11.h b/ui/base/clipboard/clipboard_x11.h
index 1fbc854..2b7a4e82 100644
--- a/ui/base/clipboard/clipboard_x11.h
+++ b/ui/base/clipboard/clipboard_x11.h
@@ -31,6 +31,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -38,9 +41,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -108,13 +108,6 @@
 
   std::vector<uint8_t> ReadPngInternal(ClipboardBuffer buffer) const;
   void OnSelectionChanged(ClipboardBuffer buffer);
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
 
   std::unique_ptr<XClipboardHelper> x_clipboard_helper_;
 
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc
index 5c8321a..cd40908 100644
--- a/ui/base/clipboard/test/test_clipboard.cc
+++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -150,27 +150,6 @@
   *types = GetStandardFormats(buffer, data_dst);
 }
 
-std::vector<std::u16string>
-TestClipboard::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer,
-    const ui::DataTransferEndpoint* data_dst) const {
-  const DataStore& store = GetStore(buffer);
-  if (!IsReadAllowed(store.data_src.get(), data_dst))
-    return {};
-
-  const auto& data = store.data;
-  std::vector<std::u16string> types;
-  types.reserve(data.size());
-  std::map<std::string, std::string> custom_format_names =
-      ExtractCustomPlatformNames(buffer, data_dst);
-  for (const auto& item : custom_format_names)
-    types.push_back(base::UTF8ToUTF16(item.first));
-  for (const auto& item : GetStandardFormats(buffer, data_dst))
-    types.push_back(item);
-
-  return types;
-}
-
 void TestClipboard::ReadText(ClipboardBuffer buffer,
                              const DataTransferEndpoint* data_dst,
                              std::u16string* result) const {
diff --git a/ui/base/clipboard/test/test_clipboard.h b/ui/base/clipboard/test/test_clipboard.h
index 72bdcc7..41832991 100644
--- a/ui/base/clipboard/test/test_clipboard.h
+++ b/ui/base/clipboard/test/test_clipboard.h
@@ -40,6 +40,9 @@
   DataTransferEndpoint* GetSource(ClipboardBuffer buffer) const override;
   const ClipboardSequenceNumberToken& GetSequenceNumber(
       ClipboardBuffer buffer) const override;
+  std::vector<std::u16string> GetStandardFormats(
+      ClipboardBuffer buffer,
+      const DataTransferEndpoint* data_dst) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
                          ClipboardBuffer buffer,
                          const DataTransferEndpoint* data_dst) const override;
@@ -47,9 +50,6 @@
   void ReadAvailableTypes(ClipboardBuffer buffer,
                           const DataTransferEndpoint* data_dst,
                           std::vector<std::u16string>* types) const override;
-  std::vector<std::u16string> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const override;
   void ReadText(ClipboardBuffer buffer,
                 const DataTransferEndpoint* data_dst,
                 std::u16string* result) const override;
@@ -139,14 +139,6 @@
   DataStore& GetStore(ClipboardBuffer buffer);
   DataStore& GetDefaultStore();
 
-  // Returns all the standard MIME types if it's present in the clipboard.
-  // The standard MIME types are the formats that are well defined by the OS.
-  // Currently we support text/html, text/plain, text/rtf, image/png &
-  // text/uri-list.
-  std::vector<std::u16string> GetStandardFormats(
-      ClipboardBuffer buffer,
-      const DataTransferEndpoint* data_dst) const;
-
   ClipboardBuffer default_store_buffer_;
   mutable base::flat_map<ClipboardBuffer, DataStore> stores_;
   base::Time last_modified_time_;
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc
index 7e6c66dc..8ae87b3 100644
--- a/ui/base/ui_base_features.cc
+++ b/ui/base/ui_base_features.cc
@@ -4,6 +4,8 @@
 
 #include "ui/base/ui_base_features.h"
 
+#include <stdlib.h>
+
 #include "build/chromeos_buildflags.h"
 
 #if defined(OS_WIN)
@@ -310,7 +312,11 @@
 
 bool ShouldApplyNativeOcclusionToCompositor() {
 #if defined(OS_WIN)
-  return base::FeatureList::IsEnabled(kCalculateNativeWinOcclusion) &&
+  // chromedriver uses the environment variable CHROME_HEADLESS. In this case
+  // it expected that native occlusion is not applied.
+  static bool is_headless = getenv("CHROME_HEADLESS") != nullptr;
+  return !is_headless &&
+         base::FeatureList::IsEnabled(kCalculateNativeWinOcclusion) &&
          base::FeatureList::IsEnabled(kApplyNativeOcclusionToCompositor);
 #else
   return false;
diff --git a/ui/chromeos/styles/cros_colors.json5 b/ui/chromeos/styles/cros_colors.json5
index 5f5e9a7..0d12b1f 100644
--- a/ui/chromeos/styles/cros_colors.json5
+++ b/ui/chromeos/styles/cros_colors.json5
@@ -80,8 +80,9 @@
       debug: "$google_red_700",
     },
 
+    dark_icon_color_primary: "$google_grey_900",
     icon_color_primary: {
-      light: "$google_grey_900",
+      light: "$dark_icon_color_primary",
       dark: "$google_grey_200",
       debug: "#ff00ff",
     },
diff --git a/ui/message_center/views/notification_input_container.cc b/ui/message_center/views/notification_input_container.cc
index 21ddbf5..2f19fb0 100644
--- a/ui/message_center/views/notification_input_container.cc
+++ b/ui/message_center/views/notification_input_container.cc
@@ -62,9 +62,11 @@
   AddChildView(textfield_);
   box_layout->SetFlexForView(textfield_, 1);
 
-  button_->SetBorder(views::CreateEmptyBorder(kInputReplyButtonPadding));
+  button_->SetBorder(views::CreateEmptyBorder(GetSendButtonPadding()));
+  SetSendButtonHighlightPath();
   button_->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
   button_->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
+
   OnAfterUserAction(textfield_);
   AddChildView(button_);
 
@@ -181,6 +183,14 @@
   return kInputTextfieldPadding;
 }
 
+gfx::Insets NotificationInputContainer::GetSendButtonPadding() const {
+  return kInputReplyButtonPadding;
+}
+
+void NotificationInputContainer::SetSendButtonHighlightPath() {
+  // Use the default highlight path.
+}
+
 void NotificationInputContainer::SetTextfieldBackground() {
   // No background.
 }
diff --git a/ui/message_center/views/notification_input_container.h b/ui/message_center/views/notification_input_container.h
index aa07244a..3b8d6a7 100644
--- a/ui/message_center/views/notification_input_container.h
+++ b/ui/message_center/views/notification_input_container.h
@@ -75,8 +75,15 @@
   // the textfield and button.
   virtual views::InkDropContainerView* InstallInkDrop();
 
+  // Gets padding for `textfield_`.
   virtual gfx::Insets GetTextfieldPadding() const;
 
+  // Gets padding for `button_`.
+  virtual gfx::Insets GetSendButtonPadding() const;
+
+  // Sets the custom highlight path for `button_`.
+  virtual void SetSendButtonHighlightPath();
+
   // Sets the visible background of `textfield_`.
   virtual void SetTextfieldBackground();
 
diff --git a/ui/views/controls/dot_indicator.cc b/ui/views/controls/dot_indicator.cc
index 413bd049..8fd7b76 100644
--- a/ui/views/controls/dot_indicator.cc
+++ b/ui/views/controls/dot_indicator.cc
@@ -13,6 +13,7 @@
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/point_f.h"
 #include "ui/gfx/geometry/rect_f.h"
+#include "ui/views/cascading_property.h"
 
 namespace views {
 
@@ -58,17 +59,22 @@
 
   // Fill the center.
   cc::PaintFlags flags;
-  flags.setColor(dot_color_);
+  flags.setColor(dot_color_.value_or(GetCascadingAccentColor(this)));
   flags.setAntiAlias(true);
   canvas->DrawCircle(center, scale * radius - kStrokeWidthPx, flags);
 
   // Draw the border.
-  flags.setColor(border_color_);
+  flags.setColor(border_color_.value_or(GetCascadingBackgroundColor(this)));
   flags.setStyle(cc::PaintFlags::kStroke_Style);
   flags.setStrokeWidth(kStrokeWidthPx * scale);
   canvas->DrawCircle(center, scale * radius - kStrokeWidthPx / 2.0f, flags);
 }
 
+void DotIndicator::OnThemeChanged() {
+  View::OnThemeChanged();
+  SchedulePaint();
+}
+
 BEGIN_METADATA(DotIndicator, View)
 END_METADATA
 
diff --git a/ui/views/controls/dot_indicator.h b/ui/views/controls/dot_indicator.h
index a1e24818..4e027f01 100644
--- a/ui/views/controls/dot_indicator.h
+++ b/ui/views/controls/dot_indicator.h
@@ -34,9 +34,10 @@
 
   // View:
   void OnPaint(gfx::Canvas* canvas) override;
+  void OnThemeChanged() override;
 
-  SkColor dot_color_ = gfx::kPlaceholderColor;
-  SkColor border_color_ = gfx::kPlaceholderColor;
+  absl::optional<SkColor> dot_color_;
+  absl::optional<SkColor> border_color_;
 };
 
 }  // namespace views
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 6905cbd..9871e3a 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -1502,7 +1502,7 @@
 
   float raster_scale = ScaleFactorForDragFromWidget(source->GetWidget());
   gfx::Canvas canvas(item->size(), raster_scale, false /* opaque */);
-  item->PaintButton(&canvas, MenuItemView::PaintButtonMode::kForDrag);
+  item->PaintForDrag(&canvas);
   gfx::ImageSkia image =
       gfx::ImageSkia::CreateFromBitmap(canvas.GetBitmap(), raster_scale);
 
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc
index 04d6a0d1..9b73a8a 100644
--- a/ui/views/controls/menu/menu_item_view.cc
+++ b/ui/views/controls/menu/menu_item_view.cc
@@ -155,6 +155,20 @@
   PreferredSizeChanged();
 }
 
+void MenuItemView::OnThemeChanged() {
+  View::OnThemeChanged();
+  // Force updating as the colors may have changed.
+  UpdateSelectionBasedState(ShouldPaintAsSelected(PaintMode::kNormal));
+}
+
+void MenuItemView::ViewHierarchyChanged(
+    const ViewHierarchyChangedDetails& details) {
+  // Whether the selection is painted may change based on the number of
+  // children.
+  if (details.parent == this)
+    UpdateSelectionBasedStateIfChanged(PaintMode::kNormal);
+}
+
 std::u16string MenuItemView::GetTooltipText(const gfx::Point& p) const {
   if (!tooltip_.empty())
     return tooltip_;
@@ -431,24 +445,33 @@
 }
 
 SubmenuView* MenuItemView::CreateSubmenu() {
-  if (!submenu_) {
-    submenu_ = new SubmenuView(this);
+  if (submenu_)
+    return submenu_;
+
+  submenu_ = new SubmenuView(this);
 
 #if defined(OS_MAC)
-    // All MenuItemViews of Type kSubMenu have a respective SubmenuView.
-    // However, in the Views hierarchy, this SubmenuView is not a child of the
-    // MenuItemView. This confuses VoiceOver, because it expects the submenu
-    // itself to be a child of the menu item. To allow VoiceOver to recognize
-    // submenu items, we create a virtual child of type Menu.
-    std::unique_ptr<AXVirtualView> virtual_child =
-        std::make_unique<AXVirtualView>();
-    virtual_child->GetCustomData().role = ax::mojom::Role::kMenu;
-    GetViewAccessibility().AddVirtualChildView(std::move(virtual_child));
+  // All MenuItemViews of Type kSubMenu have a respective SubmenuView.
+  // However, in the Views hierarchy, this SubmenuView is not a child of the
+  // MenuItemView. This confuses VoiceOver, because it expects the submenu
+  // itself to be a child of the menu item. To allow VoiceOver to recognize
+  // submenu items, we create a virtual child of type Menu.
+  std::unique_ptr<AXVirtualView> virtual_child =
+      std::make_unique<AXVirtualView>();
+  virtual_child->GetCustomData().role = ax::mojom::Role::kMenu;
+  GetViewAccessibility().AddVirtualChildView(std::move(virtual_child));
 #endif  //  defined(OS_MAC)
 
-    // Initialize the submenu indicator icon (arrow).
-    submenu_arrow_image_view_ = AddChildView(std::make_unique<ImageView>());
-  }
+  // Initialize the submenu indicator icon (arrow).
+  submenu_arrow_image_view_ = AddChildView(std::make_unique<ImageView>());
+
+  // Force an update as `submenu_arrow_image_view_` needs to be updated. The
+  // state is also updated when the theme changes (which is also called when
+  // added to a widget).
+  if (GetWidget())
+    UpdateSelectionBasedState(ShouldPaintAsSelected(PaintMode::kNormal));
+
+  SchedulePaint();
 
   return submenu_;
 }
@@ -486,7 +509,11 @@
 }
 
 void MenuItemView::SetSelected(bool selected) {
+  if (selected_ == selected)
+    return;
+
   selected_ = selected;
+  UpdateSelectionBasedStateIfChanged(PaintMode::kNormal);
   OnPropertyChanged(&selected_, kPropertyEffectsPaint);
 }
 
@@ -538,8 +565,12 @@
   SchedulePaint();
 }
 
+void MenuItemView::OnDropStatusChanged() {
+  UpdateSelectionBasedStateIfChanged(PaintMode::kNormal);
+}
+
 void MenuItemView::OnPaint(gfx::Canvas* canvas) {
-  PaintButton(canvas, PaintButtonMode::kNormal);
+  OnPaintImpl(canvas, PaintMode::kNormal);
 }
 
 gfx::Size MenuItemView::CalculatePreferredSize() const {
@@ -758,7 +789,11 @@
 }
 
 void MenuItemView::SetForcedVisualSelection(bool selected) {
+  if (selected == forced_visual_selection_)
+    return;
+
   forced_visual_selection_ = selected;
+  UpdateSelectionBasedStateIfChanged(PaintMode::kNormal);
   SchedulePaint();
 }
 
@@ -955,24 +990,27 @@
   rect->set_x(GetMirroredXForRect(*rect));
 }
 
-void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
-  bool render_selection =
-      (mode == PaintButtonMode::kNormal && IsSelected() &&
-       parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
-       (NonIconChildViewsCount() == 0));
-  if (forced_visual_selection_.has_value())
-    render_selection = *forced_visual_selection_;
+void MenuItemView::PaintForDrag(gfx::Canvas* canvas) {
+  // Selection state may change when painting a drag operation. Set state for
+  // a drag operation, paint, and then set state back to non-drag (normal)
+  // state.
+  UpdateSelectionBasedStateIfChanged(PaintMode::kForDrag);
+  OnPaintImpl(canvas, PaintMode::kForDrag);
+  UpdateSelectionBasedStateIfChanged(PaintMode::kNormal);
+}
+
+void MenuItemView::OnPaintImpl(gfx::Canvas* canvas, PaintMode mode) {
+  const bool paint_as_selected = ShouldPaintAsSelected(mode);
+  // If these are out of sync, UpdateSelectionBasedStateIfChanged() was not
+  // called.
+  DCHECK_EQ(paint_as_selected, last_paint_as_selected_);
 
   // Render the background. As MenuScrollViewContainer draws the background, we
   // only need the background when we want it to look different, as when we're
   // selected.
-  PaintBackground(canvas, mode, render_selection);
+  PaintBackground(canvas, mode, paint_as_selected);
 
-  // Calculate some colors.
-  SkColor fg_color = GetTextColor(/*minor=*/false, render_selection);
-  if (const auto& label_color = GetMenuLabelColor())
-    fg_color = label_color.value();
-  SkColor icon_color = color_utils::DeriveDefaultIconColor(fg_color);
+  const Colors colors = CalculateColors(paint_as_selected);
 
   const gfx::FontList& font_list = GetFontList();
 
@@ -985,22 +1023,6 @@
       secondary_title().empty() ? text_height : text_height * 2;
   top_margin += (available_height - total_text_height) / 2;
 
-  // Render the check.
-  MenuDelegate* delegate = GetDelegate();
-  if (type_ == Type::kCheckbox && delegate &&
-      delegate->IsItemChecked(GetCommand())) {
-    radio_check_image_view_->SetImage(GetMenuCheckImage(icon_color));
-  } else if (type_ == Type::kRadio) {
-    const bool toggled = delegate && delegate->IsItemChecked(GetCommand());
-    const gfx::VectorIcon& radio_icon =
-        toggled ? kMenuRadioSelectedIcon : kMenuRadioEmptyIcon;
-    const SkColor radio_icon_color = GetColorProvider()->GetColor(
-        toggled ? ui::kColorButtonForegroundChecked
-                : ui::kColorButtonForegroundUnchecked);
-    radio_check_image_view_->SetImage(
-        gfx::CreateVectorIcon(radio_icon, kMenuCheckSize, radio_icon_color));
-  }
-
   // Render the foreground.
   int accel_width = parent_menu_item_->GetSubmenu()->max_minor_text_width();
   int label_start = GetLabelStartForThisItem();
@@ -1009,20 +1031,19 @@
   gfx::Rect text_bounds(label_start, top_margin, width, text_height);
   text_bounds.set_x(GetMirroredXForRect(text_bounds));
   int flags = GetDrawStringFlags();
-  if (mode == PaintButtonMode::kForDrag)
+  if (mode == PaintMode::kForDrag)
     flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
-  canvas->DrawStringRectWithFlags(title(), font_list, fg_color, text_bounds,
-                                  flags);
+  canvas->DrawStringRectWithFlags(title(), font_list, colors.fg_color,
+                                  text_bounds, flags);
 
   // The rest should be drawn with the minor foreground color.
-  fg_color = GetTextColor(/*minor=*/true, render_selection);
   if (!secondary_title().empty()) {
     text_bounds.set_y(text_bounds.y() + text_height);
-    canvas->DrawStringRectWithFlags(secondary_title(), font_list, fg_color,
-                                    text_bounds, flags);
+    canvas->DrawStringRectWithFlags(secondary_title(), font_list,
+                                    colors.minor_fg_color, text_bounds, flags);
   }
 
-  PaintMinorIconAndText(canvas, fg_color);
+  PaintMinorIconAndText(canvas, colors.minor_fg_color);
 
   if (ShouldShowNewBadge()) {
     NewBadge::DrawNewBadge(canvas, this,
@@ -1031,23 +1052,19 @@
                                NewBadge::kNewBadgeHorizontalMargin,
                            top_margin, font_list);
   }
-
-  // Set the submenu indicator (arrow) image and color.
-  if (HasSubmenu())
-    submenu_arrow_image_view_->SetImage(GetSubmenuArrowImage(icon_color));
 }
 
 void MenuItemView::PaintBackground(gfx::Canvas* canvas,
-                                   PaintButtonMode mode,
-                                   bool render_selection) {
+                                   PaintMode mode,
+                                   bool paint_as_selected) {
   if (type_ == Type::kHighlighted || is_alerted_) {
     SkColor color = gfx::kPlaceholderColor;
 
     ui::ColorProvider* color_provider = GetColorProvider();
     if (type_ == Type::kHighlighted) {
       const ui::ColorId color_id =
-          render_selection ? ui::kColorMenuItemBackgroundSelected
-                           : ui::kColorMenuItemBackgroundHighlighted;
+          paint_as_selected ? ui::kColorMenuItemBackgroundSelected
+                            : ui::kColorMenuItemBackgroundHighlighted;
       color = color_provider->GetColor(color_id);
     } else {
       const auto* animation = GetMenuController()->GetAlertAnimation();
@@ -1071,7 +1088,7 @@
     spilling_rect.set_y(spilling_rect.y() - corner_radius_);
     spilling_rect.set_height(spilling_rect.height() + corner_radius_);
     canvas->DrawRoundRect(spilling_rect, corner_radius_, flags);
-  } else if (render_selection) {
+  } else if (paint_as_selected) {
     gfx::Rect item_bounds = GetLocalBounds();
     if (type_ == Type::kActionableSubMenu) {
       if (submenu_area_of_actionable_submenu_selected_) {
@@ -1136,7 +1153,7 @@
   }
 }
 
-SkColor MenuItemView::GetTextColor(bool minor, bool render_selection) const {
+SkColor MenuItemView::GetTextColor(bool minor, bool paint_as_selected) const {
   style::TextContext context =
       GetMenuController() && GetMenuController()->use_touchable_layout()
           ? style::CONTEXT_TOUCH_MENU
@@ -1149,7 +1166,7 @@
     text_style = style::STYLE_HIGHLIGHTED;
   else if (!GetEnabled())
     text_style = style::STYLE_DISABLED;
-  else if (render_selection)
+  else if (paint_as_selected)
     text_style = style::STYLE_SELECTED;
   else if (minor)
     text_style = style::STYLE_SECONDARY;
@@ -1157,6 +1174,18 @@
   return style::GetColor(*this, context, text_style);
 }
 
+MenuItemView::Colors MenuItemView::CalculateColors(
+    bool paint_as_selected) const {
+  const absl::optional<SkColor> label_color_from_delegate = GetMenuLabelColor();
+  Colors colors;
+  colors.fg_color = label_color_from_delegate
+                        ? *label_color_from_delegate
+                        : GetTextColor(/*minor=*/false, paint_as_selected);
+  colors.icon_color = color_utils::DeriveDefaultIconColor(colors.fg_color);
+  colors.minor_fg_color = GetTextColor(/*minor=*/true, paint_as_selected);
+  return colors;
+}
+
 std::u16string MenuItemView::GetAccessibleName() const {
   std::u16string item_text = accessible_name();
   if (!item_text.empty())
@@ -1441,6 +1470,51 @@
       [](const auto* item) { return item->HasChecksOrRadioButtons(); });
 }
 
+void MenuItemView::UpdateSelectionBasedStateIfChanged(PaintMode mode) {
+  // Selection state depends upon NativeTheme.
+  if (!GetWidget())
+    return;
+
+  const bool paint_as_selected = ShouldPaintAsSelected(mode);
+  if (paint_as_selected != last_paint_as_selected_)
+    UpdateSelectionBasedState(paint_as_selected);
+}
+
+void MenuItemView::UpdateSelectionBasedState(bool paint_as_selected) {
+  // This code makes use of the NativeTheme, which should only be accessed
+  // when in a Widget.
+  DCHECK(GetWidget());
+  last_paint_as_selected_ = paint_as_selected;
+  const Colors colors = CalculateColors(paint_as_selected);
+  if (submenu_arrow_image_view_) {
+    submenu_arrow_image_view_->SetImage(
+        GetSubmenuArrowImage(colors.icon_color));
+  }
+  MenuDelegate* delegate = GetDelegate();
+  if (type_ == Type::kCheckbox && delegate &&
+      delegate->IsItemChecked(GetCommand())) {
+    radio_check_image_view_->SetImage(GetMenuCheckImage(colors.icon_color));
+  } else if (type_ == Type::kRadio) {
+    const bool toggled = delegate && delegate->IsItemChecked(GetCommand());
+    const gfx::VectorIcon& radio_icon =
+        toggled ? kMenuRadioSelectedIcon : kMenuRadioEmptyIcon;
+    const SkColor radio_icon_color = GetColorProvider()->GetColor(
+        toggled ? ui::kColorButtonForegroundChecked
+                : ui::kColorButtonForegroundUnchecked);
+    radio_check_image_view_->SetImage(
+        gfx::CreateVectorIcon(radio_icon, kMenuCheckSize, radio_icon_color));
+  }
+}
+
+bool MenuItemView::ShouldPaintAsSelected(PaintMode mode) const {
+  if (forced_visual_selection_.has_value())
+    return true;
+
+  return (parent_menu_item_ && mode == PaintMode::kNormal && IsSelected() &&
+          parent_menu_item_->GetSubmenu()->GetShowSelection(this) &&
+          (NonIconChildViewsCount() == 0));
+}
+
 BEGIN_METADATA(MenuItemView, View)
 END_METADATA
 
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h
index 302cadfd7..af042b77 100644
--- a/ui/views/controls/menu/menu_item_view.h
+++ b/ui/views/controls/menu/menu_item_view.h
@@ -15,6 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/models/menu_separator_types.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/image/image_skia.h"
@@ -284,6 +285,9 @@
   }
   const std::u16string& accessible_name() const { return accessible_name_; }
 
+  // Called when the drop status of this item changes.
+  void OnDropStatusChanged();
+
   // Paints the menu item.
   void OnPaint(gfx::Canvas* canvas) override;
 
@@ -379,6 +383,9 @@
 
   // View:
   void ChildPreferredSizeChanged(View* child) override;
+  void OnThemeChanged() override;
+  void ViewHierarchyChanged(
+      const ViewHierarchyChangedDetails& details) override;
 
   // Returns the preferred size (and padding) of any children.
   virtual gfx::Size GetChildPreferredSize() const;
@@ -393,7 +400,14 @@
   friend class test::TestMenuItemViewNotShown;  // for access to |submenu_|;
   friend class TestMenuItemView;  // For access to AddEmptyMenus();
 
-  enum class PaintButtonMode { kNormal, kForDrag };
+  enum class PaintMode { kNormal, kForDrag };
+
+  // The set of colors used in painting the MenuItemView.
+  struct Colors {
+    SkColor fg_color = SK_ColorTRANSPARENT;
+    SkColor icon_color = SK_ColorTRANSPARENT;
+    SkColor minor_fg_color = SK_ColorTRANSPARENT;
+  };
 
   // Calculates all sizes that we can from the OS.
   //
@@ -428,15 +442,17 @@
   // necessary.
   void AdjustBoundsForRTLUI(gfx::Rect* rect) const;
 
-  // Actual paint implementation. If mode is kForDrag, portions of the menu are
-  // not rendered.
-  void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode);
+  // Paints the MenuItemView for a drag operation.
+  void PaintForDrag(gfx::Canvas* canvas);
 
-  // Helper function for PaintButton(), draws the background for the button if
-  // appropriate.
+  // Actual paint implementation.
+  void OnPaintImpl(gfx::Canvas* canvas, PaintMode mode);
+
+  // Helper function for OnPaintImpl() that is responsible for drawing the
+  // background.
   void PaintBackground(gfx::Canvas* canvas,
-                       PaintButtonMode mode,
-                       bool render_selection);
+                       PaintMode mode,
+                       bool paint_as_selected);
 
   // Paints the right-side icon and text.
   void PaintMinorIconAndText(gfx::Canvas* canvas, SkColor color);
@@ -454,7 +470,10 @@
 
   // Returns the text color for the current state.  |minor| specifies if the
   // minor text or the normal text is desired.
-  SkColor GetTextColor(bool minor, bool render_selection) const;
+  SkColor GetTextColor(bool minor, bool paint_as_selected) const;
+
+  // Returns the colors used in painting.
+  Colors CalculateColors(bool paint_as_selected) const;
 
   // Returns the accessible name for this menu item.
   std::u16string GetAccessibleName() const;
@@ -506,6 +525,15 @@
   void invalidate_dimensions() { dimensions_.height = 0; }
   bool is_dimensions_valid() const { return dimensions_.height > 0; }
 
+  // Calls UpdateSelectionBasedState() if the the selection state changed.
+  void UpdateSelectionBasedStateIfChanged(PaintMode mode);
+
+  // Updates any state that may changed based on the selection state.
+  void UpdateSelectionBasedState(bool should_paint_as_selected);
+
+  // Returns true if the MenuItemView should be painted as selected.
+  bool ShouldPaintAsSelected(PaintMode mode) const;
+
   // The delegate. This is only valid for the root menu item. You shouldn't
   // use this directly, instead use GetDelegate() which walks the tree as
   // as necessary.
@@ -527,6 +555,8 @@
   // Whether we're selected.
   bool selected_ = false;
 
+  bool last_paint_as_selected_ = false;
+
   // Whether the submenu area of an ACTIONABLE_SUBMENU is selected.
   bool submenu_area_of_actionable_submenu_selected_ = false;
 
diff --git a/ui/views/controls/menu/menu_item_view_unittest.cc b/ui/views/controls/menu/menu_item_view_unittest.cc
index b3a1c8d..f4a74a3 100644
--- a/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -13,9 +13,11 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/compositor/canvas_painter.h"
+#include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/native_theme/themed_vector_icon.h"
 #include "ui/strings/grit/ui_strings.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/controls/menu/submenu_view.h"
 #include "ui/views/controls/menu/test_menu_item_view.h"
@@ -23,6 +25,7 @@
 #include "ui/views/test/views_test_base.h"
 #include "ui/views/vector_icons.h"
 #include "ui/views/view_class_properties.h"
+#include "ui/views/view_test_api.h"
 
 namespace views {
 
@@ -260,7 +263,7 @@
 
 class MenuItemViewLayoutTest : public ViewsTestBase {
  public:
-  MenuItemViewLayoutTest() : test_item_(root_menu_.AppendMenuItem(1)) {}
+  MenuItemViewLayoutTest() = default;
   ~MenuItemViewLayoutTest() override = default;
 
  protected:
@@ -269,7 +272,7 @@
   void PerformLayout() {
     // SubmenuView does not lay out its children unless it is contained in a
     // view, so make a simple container for it.
-    SubmenuView* submenu = root_menu_.GetSubmenu();
+    SubmenuView* submenu = root_menu_->GetSubmenu();
     ASSERT_TRUE(submenu->owned_by_client());
 
     submenu_parent_ = std::make_unique<View>();
@@ -278,9 +281,15 @@
     submenu_parent_->SetSize(submenu->GetPreferredSize());
   }
 
+  void SetUp() override {
+    ViewsTestBase::SetUp();
+    root_menu_ = std::make_unique<TestMenuItemView>();
+    test_item_ = root_menu_->AppendMenuItem(1);
+  }
+
  private:
-  TestMenuItemView root_menu_;
-  MenuItemView* const test_item_;
+  std::unique_ptr<TestMenuItemView> root_menu_;
+  MenuItemView* test_item_ = nullptr;
   std::unique_ptr<View> submenu_parent_;
 };
 
@@ -373,7 +382,7 @@
   // ViewsTestBase implementation.
   void SetUp() override {
     ViewsTestBase::SetUp();
-    menu_delegate_ = std::make_unique<test::TestMenuDelegate>();
+    menu_delegate_ = CreateMenuDelegate();
     menu_item_view_ = new MenuItemView(menu_delegate_.get());
 
     widget_ = std::make_unique<Widget>();
@@ -390,6 +399,11 @@
     ViewsTestBase::TearDown();
   }
 
+ protected:
+  virtual std::unique_ptr<test::TestMenuDelegate> CreateMenuDelegate() {
+    return std::make_unique<test::TestMenuDelegate>();
+  }
+
  private:
   // Owned by MenuRunner.
   MenuItemView* menu_item_view_;
@@ -440,4 +454,59 @@
       PaintInfo::CreateRootPaintInfo(canvas_painter.context(), size));
 }
 
+// Verifies a call to MenuItemView::OnPaint() doesn't trigger a call to
+// MenuItemView::submenu_arrow_image_view_::SchedulePaint(). This is a
+// regression test for https://crbug.com/1245854.
+TEST_F(MenuItemViewPaintUnitTest, DontSchedulePaintFromOnPaint) {
+  MenuItemView* submenu_item =
+      menu_item_view()->AppendSubMenu(1, u"My Submenu");
+  submenu_item->AppendMenuItem(1, u"submenu item 1");
+
+  menu_runner()->RunMenuAt(widget(), nullptr, gfx::Rect(),
+                           MenuAnchorPosition::kTopLeft,
+                           ui::MENU_SOURCE_KEYBOARD);
+
+  ImageView* submenu_arrow_image_view =
+      TestMenuItemView::submenu_arrow_image_view(submenu_item);
+  ASSERT_TRUE(submenu_arrow_image_view);
+  ViewTestApi(submenu_arrow_image_view).ClearNeedsPaint();
+
+  // Paint again. As no state has changed since the last paint, this should not
+  // call SchedulePaint() on the `submenu_arrow_image_view`
+  gfx::Canvas canvas(submenu_item->size(), 1.f, false /* opaque */);
+  submenu_item->OnPaint(&canvas);
+  EXPECT_FALSE(ViewTestApi(submenu_arrow_image_view).needs_paint());
+}
+
+// Sets up a custom MenuDelegate that expects functions aren't called. See
+// DontAskForFontsWhenAddingSubmenu.
+class MenuItemViewAccessTest : public MenuItemViewPaintUnitTest {
+ public:
+ protected:
+  std::unique_ptr<test::TestMenuDelegate> CreateMenuDelegate() override {
+    return std::make_unique<DisallowMenuDelegate>();
+  }
+
+ private:
+  class DisallowMenuDelegate : public test::TestMenuDelegate {
+   public:
+    const gfx::FontList* GetLabelFontList(int command_id) const override {
+      EXPECT_NE(1, command_id);
+      return nullptr;
+    }
+
+    absl::optional<SkColor> GetLabelColor(int command_id) const override {
+      EXPECT_NE(1, command_id);
+      return absl::nullopt;
+    }
+  };
+};
+
+// Verifies AppendSubMenu() doesn't trigger calls to the delegate with the
+// command being supplied. The delegate can be called after AppendSubMenu(),
+// but not before.
+TEST_F(MenuItemViewAccessTest, DontAskForFontsWhenAddingSubmenu) {
+  menu_item_view()->AppendSubMenu(1, u"My Submenu");
+}
+
 }  // namespace views
diff --git a/ui/views/controls/menu/submenu_view.cc b/ui/views/controls/menu/submenu_view.cc
index e7fb0a4..cc2cd65 100644
--- a/ui/views/controls/menu/submenu_view.cc
+++ b/ui/views/controls/menu/submenu_view.cc
@@ -482,12 +482,17 @@
   if (drop_item_ == item && drop_position_ == position)
     return;
   SchedulePaintForDropIndicator(drop_item_, drop_position_);
+  MenuItemView* old_drop_item = drop_item_;
   drop_item_ = item;
   drop_position_ = position;
+  if (old_drop_item && old_drop_item != drop_item_)
+    old_drop_item->OnDropStatusChanged();
+  if (drop_item_)
+    drop_item_->OnDropStatusChanged();
   SchedulePaintForDropIndicator(drop_item_, drop_position_);
 }
 
-bool SubmenuView::GetShowSelection(MenuItemView* item) {
+bool SubmenuView::GetShowSelection(const MenuItemView* item) const {
   if (drop_item_ == nullptr)
     return true;
   // Something is being dropped on one of this menus items. Show the
diff --git a/ui/views/controls/menu/submenu_view.h b/ui/views/controls/menu/submenu_view.h
index 5367383..536f57da 100644
--- a/ui/views/controls/menu/submenu_view.h
+++ b/ui/views/controls/menu/submenu_view.h
@@ -154,7 +154,7 @@
   // Returns whether the selection should be shown for the specified item.
   // The selection is NOT shown during drag and drop when the drop is over
   // the menu.
-  bool GetShowSelection(MenuItemView* item);
+  bool GetShowSelection(const MenuItemView* item) const;
 
   // Returns the container for the SubmenuView.
   MenuScrollViewContainer* GetScrollViewContainer();
diff --git a/ui/views/controls/menu/submenu_view_unittest.cc b/ui/views/controls/menu/submenu_view_unittest.cc
index f277cd1..7a05e2e 100644
--- a/ui/views/controls/menu/submenu_view_unittest.cc
+++ b/ui/views/controls/menu/submenu_view_unittest.cc
@@ -7,10 +7,13 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/views/controls/menu/menu_item_view.h"
 #include "ui/views/controls/menu/menu_runner.h"
+#include "ui/views/test/views_test_base.h"
 
 namespace views {
 
-TEST(SubmenuViewTest, GetLastItem) {
+using SubmenuViewTest = ViewsTestBase;
+
+TEST_F(SubmenuViewTest, GetLastItem) {
   MenuItemView* parent = new MenuItemView();
   MenuRunner menu_runner(parent, 0);
 
diff --git a/ui/views/controls/menu/test_menu_item_view.h b/ui/views/controls/menu/test_menu_item_view.h
index 7ce6bb0..9e42565 100644
--- a/ui/views/controls/menu/test_menu_item_view.h
+++ b/ui/views/controls/menu/test_menu_item_view.h
@@ -28,6 +28,10 @@
   void set_has_mnemonics(bool has_mnemonics) { has_mnemonics_ = has_mnemonics; }
 
   bool show_mnemonics() { return show_mnemonics_; }
+
+  static ImageView* submenu_arrow_image_view(MenuItemView* view) {
+    return view->submenu_arrow_image_view_;
+  }
 };
 
 }  // namespace views
diff --git a/ui/views/test/scoped_views_test_helper.cc b/ui/views/test/scoped_views_test_helper.cc
index 9e5d355..8136531 100644
--- a/ui/views/test/scoped_views_test_helper.cc
+++ b/ui/views/test/scoped_views_test_helper.cc
@@ -8,7 +8,6 @@
 
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/test/test_clipboard.h"
-#include "ui/views/test/test_views_delegate.h"
 
 #if defined(USE_AURA)
 #include "ui/aura/window.h"
diff --git a/ui/views/test/scoped_views_test_helper.h b/ui/views/test/scoped_views_test_helper.h
index a34fb0a..78caf2a 100644
--- a/ui/views/test/scoped_views_test_helper.h
+++ b/ui/views/test/scoped_views_test_helper.h
@@ -10,12 +10,12 @@
 #include "base/macros.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/native_widget_types.h"
+#include "ui/views/test/test_views_delegate.h"
 #include "ui/views/test/views_test_helper.h"
 #include "ui/views/views_delegate.h"
 
 namespace views {
 
-class TestViewsDelegate;
 class Widget;
 
 // Creates a ViewsTestHelper that is destroyed automatically. Acts like
diff --git a/ui/views/view_test_api.h b/ui/views/view_test_api.h
index 59195b9..18703ba 100644
--- a/ui/views/view_test_api.h
+++ b/ui/views/view_test_api.h
@@ -20,6 +20,9 @@
 
   bool needs_layout() { return view_->needs_layout(); }
 
+  void ClearNeedsPaint() { view_->needs_paint_ = false; }
+  bool needs_paint() const { return view_->needs_paint_; }
+
  private:
   View* view_;
 };
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html
index 95d7ced..c78a9dd 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.html
@@ -29,12 +29,6 @@
         margin: 8px 0 8px 32px;
       }
 
-      .cellular-not-setup {
-        color: var(--google-grey-700);
-        font-size: smaller;
-        margin-bottom: 16px;
-      }
-
       #qrCodeCanvas {
         display: block;
         margin: 20px auto 16px auto;
@@ -43,6 +37,16 @@
             var(--cr-dialog-title-slot-padding-end));
       }
 
+      @media(prefers-color-scheme: dark) {
+        /* NOTE: In dark mode a light background is applied to the QR code
+         * canvas as some QR code scanners cannot read an inverted QR code in
+         * which the background is darker than the foreground. */
+        #qrCodeCanvas {
+          background-color: var(--cros-icon-color-primary);
+          padding: 1px;
+        }
+      }
+
       #eid {
         margin-top: 16px;
       }
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js
index f6a23de6..9be4aec 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/cellular_eid_dialog.js
@@ -8,8 +8,6 @@
 
 // The size of each tile in pixels.
 const QR_CODE_TILE_SIZE = 5;
-// Styling for filled tiles in the QR code.
-const QR_CODE_FILL_STYLE = '#000000';
 
 Polymer({
   is: 'cellular-eid-dialog',
@@ -65,7 +63,8 @@
     Polymer.dom.flush();
     const context = this.getCanvasContext_();
     context.clearRect(0, 0, this.canvasSize_, this.canvasSize_);
-    context.fillStyle = QR_CODE_FILL_STYLE;
+    context.fillStyle = getComputedStyle(this.$.qrCodeCanvas)
+                            .getPropertyValue('--cros-dark-icon-color-primary');
     let index = 0;
     for (let x = 0; x < response.qrCode.size; x++) {
       for (let y = 0; y < response.qrCode.size; y++) {
diff --git a/ui/webui/resources/cr_components/chromeos/network_health/routine_group.html b/ui/webui/resources/cr_components/chromeos/network_health/routine_group.html
index 0682ae7..88d043a 100644
--- a/ui/webui/resources/cr_components/chromeos/network_health/routine_group.html
+++ b/ui/webui/resources/cr_components/chromeos/network_health/routine_group.html
@@ -29,10 +29,10 @@
     <network-health-container expanded="[[expanded]]" label="[[name]]"
         on-toggle-expanded="onToggleExpanded_">
       <span slot="header" >
-        <template is="dom-if" if="[[running]]">
+        <template is="dom-if" if="[[running_]]">
           <paper-spinner-lite active></paper-spinner-lite>
         </template>
-        <img class="routine-icon" hidden="[[!showGroupIcon]]"
+        <img class="routine-icon" hidden="[[!showGroupIcon_]]"
             src="[[getGroupIcon_(routines.*)]]">
       </span>
       <template is="dom-repeat" items="[[routines]]" as="routine"
diff --git a/ui/webui/resources/cr_components/chromeos/network_health/routine_group.js b/ui/webui/resources/cr_components/chromeos/network_health/routine_group.js
index 7646700..80d5a72 100644
--- a/ui/webui/resources/cr_components/chromeos/network_health/routine_group.js
+++ b/ui/webui/resources/cr_components/chromeos/network_health/routine_group.js
@@ -16,7 +16,7 @@
   properties: {
     /**
      * List of routines to display in the group.
-     * @private {!Array<!Routine>}
+     * @type {!Array<!Routine>}
      */
     routines: {
       type: Array,
@@ -25,7 +25,7 @@
 
     /**
      * Localized name for the group of routines.
-     * @private {String}
+     * @type {string}
      */
     name: {
       type: String,
@@ -33,17 +33,8 @@
     },
 
     /**
-     * Boolean flag if any routines in the group are running.
-     * @private {Boolean}
-     */
-    running: {
-      type: Boolean,
-      computed: 'routinesRunning_(routines.*)',
-    },
-
-    /**
      * Boolean flag if the container is expanded.
-     * @private {Boolean}
+     * @type {boolean}
      */
     expanded: {
       type: Boolean,
@@ -51,12 +42,21 @@
     },
 
     /**
-     * Boolean flag if icon representing the group result should be shown.
-     * @private {Boolean}
+     * Boolean flag if any routines in the group are running.
+     * @private {boolean}
      */
-    showGroupIcon: {
+    running_: {
       type: Boolean,
-      computed: 'showGroupIcon_(running, expanded)',
+      computed: 'routinesRunning_(routines.*)',
+    },
+
+    /**
+     * Boolean flag if icon representing the group result should be shown.
+     * @private {boolean}
+     */
+    showGroupIcon_: {
+      type: Boolean,
+      computed: 'computeShowGroupIcon_(running_, expanded)',
     },
   },
 
@@ -102,13 +102,11 @@
 
   /**
    * Determine if the group routine icon should be showing.
-   * @param {boolean} running
-   * @param {boolean} expanded
    * @return {boolean}
    * @private
    */
-  showGroupIcon_(running, expanded) {
-    return !running && !expanded;
+  computeShowGroupIcon_() {
+    return !this.running_ && !this.expanded;
   },
 
   /**