diff --git a/DEPS b/DEPS
index e1a38e4..fd570c6 100644
--- a/DEPS
+++ b/DEPS
@@ -283,7 +283,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '593cd597a31e649f7219d3bdd021b76ec2f835c1',
+  'angle_revision': 'a65af046953a0a16ceed4ad1dbb91fb377bf245b',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -302,7 +302,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:8.20220608.1.1',
+  'fuchsia_version': 'version:8.20220608.4.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -346,7 +346,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': '45853b3700cddd1f4eefe531f18add46e6c90e76',
+  'catapult_revision': '8a8c0b9c3967e17da1d9f64b3d57e4a969b465a7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -354,7 +354,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '0cca99b9409a03b9523f1d5cd13675b5fc0aed62',
+  'devtools_frontend_revision': 'ac6b02745945218c6e79b2adb8ef987f892fc141',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -771,7 +771,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '2eaeeed3b8899aa76e3f6defd20e7d7d89eeb360',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '8225446a8df15e53e96304852f134259e0e5e2df',
       'condition': 'checkout_ios',
   },
 
@@ -1059,7 +1059,7 @@
   },
 
   'src/third_party/breakpad/breakpad':
-    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + '8b68c72a3fff2bb687c7f411e5c1c09e356b8603',
+    Var('chromium_git') + '/breakpad/breakpad.git' + '@' + 'c4c43b80ea8854c57a4374ac32579b577172dc23',
 
   'src/third_party/byte_buddy': {
       'packages': [
@@ -1136,7 +1136,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8199bccb81a85678d731941c1ac5130a72014834',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b3579d428a79e0425f4d3d9be58d76470f96fb6b',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1425,7 +1425,7 @@
     Var('chromium_git') + '/webm/libwebm.git' + '@' + 'e4fbea0c9751ae8aa86629b197a28d8276a2b0da',
 
   'src/third_party/libyuv':
-    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'd62ee21e6627888e84466b5a5ed15775582ac67b',
+    Var('chromium_git') + '/libyuv/libyuv.git' + '@' + 'baef41447887e1a17897a4cb6ccc854ef3a9d652',
 
   'src/third_party/lighttpd': {
       'url': Var('chromium_git') + '/chromium/deps/lighttpd.git' + '@' + Var('lighttpd_revision'),
@@ -1533,7 +1533,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '31772328c517b725c81994e4b9b99aac18319e40',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'db7def5150207a574e8955afc591a5650b3ad290',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1669,7 +1669,7 @@
       'condition': 'checkout_android',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@23b710f1a0b3c44d51035c6400a554415f95d9c6',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@1190dc2b6863cf0137ac4c2d323c66c8887c8e4e',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'ebe84bec02c041d28f902da0214bf442743fc907',
@@ -1708,7 +1708,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'edd275f0ad33c708fba30643cf971adf0f6ba488',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'ca6726d5c47156b6ed79a19d186b5bdb3384ff41',
+    Var('webrtc_git') + '/src.git' + '@' + 'da0ea972364f23d21893cf58701ce8ccd798c1c4',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1781,7 +1781,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@e07d4ea1bf521f8fcfc328290cb212074b7e138b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ea11a9525684a5ba7962ca95a9a42511bc0697a8',
     'condition': 'checkout_src_internal',
   },
 
@@ -1811,7 +1811,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '-r5clhZKMsKXeyTvDOdrDvtevLMbxBxCv4TpRaK5SK4C',
+        'version': '7Wk1Iwgo26iCC0y5AnlUH7ejxibcMH_hpnDFC1GYhWMC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/gfx/BUILD.gn b/android_webview/browser/gfx/BUILD.gn
index b313bc7..7062171 100644
--- a/android_webview/browser/gfx/BUILD.gn
+++ b/android_webview/browser/gfx/BUILD.gn
@@ -83,7 +83,6 @@
     "//content/public/browser",
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/service",
-    "//gpu/ipc:gl_in_process_context",
     "//gpu/ipc/common:android_image_reader_utils",
     "//gpu/ipc/common:common",
     "//gpu/skia_bindings",
diff --git a/android_webview/lib/BUILD.gn b/android_webview/lib/BUILD.gn
index 408f059..66e2365 100644
--- a/android_webview/lib/BUILD.gn
+++ b/android_webview/lib/BUILD.gn
@@ -44,7 +44,6 @@
     "//gin",
     "//gpu/command_buffer/service",
     "//gpu/config",
-    "//gpu/ipc:gl_in_process_context",
     "//media",
     "//media:media_buildflags",
     "//third_party/blink/public/common:headers",
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc
index c4520c5..aa6c6da 100644
--- a/android_webview/lib/aw_main_delegate.cc
+++ b/android_webview/lib/aw_main_delegate.cc
@@ -59,7 +59,6 @@
 #include "gin/v8_initializer.h"
 #include "gpu/command_buffer/service/gpu_switches.h"
 #include "gpu/config/gpu_finch_features.h"
-#include "gpu/ipc/gl_in_process_context.h"
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
 #include "services/network/public/cpp/features.h"
diff --git a/android_webview/tools/automated_ui_tests/BUILD.gn b/android_webview/tools/automated_ui_tests/BUILD.gn
index 6007e2f..5645be1 100644
--- a/android_webview/tools/automated_ui_tests/BUILD.gn
+++ b/android_webview/tools/automated_ui_tests/BUILD.gn
@@ -63,9 +63,9 @@
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java_test_support",
   ]
   data = [ "test/data/" ]
diff --git a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
index 517db69..9f3dab8 100644
--- a/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
+++ b/android_webview/tools/automated_ui_tests/javatests/src/org/chromium/webview_ui_test/test/ActionModeTest.java
@@ -43,9 +43,6 @@
 import android.content.Intent;
 import android.os.Build;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
 import android.view.MenuItem;
 
 import androidx.test.espresso.NoMatchingViewException;
@@ -58,6 +55,9 @@
 import androidx.test.espresso.intent.Intents;
 import androidx.test.espresso.web.webdriver.Locator;
 import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
 
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 54d0fc4..d0680b6 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -3170,6 +3170,7 @@
   sources = [
     "test/ash_pixel_diff_test_base.cc",
     "test/ash_pixel_diff_test_base.h",
+    "test/demo_ash_pixel_diff_test.cc",
   ]
 
   deps = [
diff --git a/ash/ambient/ambient_controller.cc b/ash/ambient/ambient_controller.cc
index 747186a..a02ae49 100644
--- a/ash/ambient/ambient_controller.cc
+++ b/ash/ambient/ambient_controller.cc
@@ -888,11 +888,7 @@
     current_theme = animation_experiment_enabled.value()
                         ? features::kAmbientModeAnimationThemeParam.Get()
                         : kDefaultAmbientAnimationTheme;
-  } else if (features::IsPersonalizationHubEnabled()) {
-    // UX testers/dogfooders only have to enable the personalization hub to get
-    // the animation. They do not turn on the dedicated animation experiment
-    // flag as that is only intended for developers who want to bypass the hub.
-    // If the hub is disabled, fallback to the default theme.
+  } else if (features::IsAmbientModeAnimationEnabled()) {
     DCHECK(current_theme_from_pref_);
     current_theme = *current_theme_from_pref_;
   }
diff --git a/ash/ambient/ambient_controller_unittest.cc b/ash/ambient/ambient_controller_unittest.cc
index a4e90de9..13eafdf 100644
--- a/ash/ambient/ambient_controller_unittest.cc
+++ b/ash/ambient/ambient_controller_unittest.cc
@@ -1190,43 +1190,57 @@
 }
 
 TEST_P(AmbientControllerTestForAnyTheme, MetricsEngagementTime) {
+  // TODO(esum): Find a better way of fast forwarding time for lottie animations
+  // in unit tests. Currently, the whole compositor stack is being used in this
+  // test harness and there is no good way to control the frame rate, so
+  // FastForwardBy() blocks for long periods of time. Do not make this value
+  // too high, or the test is at risk of timing out.
+  constexpr base::TimeDelta kExpectedEngagementTime = base::Milliseconds(100);
+
   base::HistogramTester histogram_tester;
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(false);
   LockScreen();
 
-  FastForwardToLockScreenTimeout();
-  FastForwardTiny();
+  // Unlike other tests, the exact amount of time we spend in ambient mode
+  // matters to write the correct test expectation. So fast forward by the
+  // exact amount needed to trigger ambient mode.
+  // (FastForwardToLockScreenTimeout() adds on a little buffer to the timeout)
+  task_environment()->FastForwardBy(ambient_controller()
+                                        ->ambient_ui_model()
+                                        ->lock_screen_inactivity_timeout());
   ASSERT_TRUE(ambient_controller()->IsShown());
 
-  task_environment()->FastForwardBy(base::Minutes(1));
+  task_environment()->FastForwardBy(kExpectedEngagementTime);
 
   UnlockScreen();
   ASSERT_FALSE(ambient_controller()->IsShown());
 
   histogram_tester.ExpectTimeBucketCount(
-      "Ash.AmbientMode.EngagementTime.ClamshellMode", base::Minutes(1), 1);
+      "Ash.AmbientMode.EngagementTime.ClamshellMode", kExpectedEngagementTime,
+      1);
   histogram_tester.ExpectTimeBucketCount(
       base::StrCat({"Ash.AmbientMode.EngagementTime.", ToString(GetParam())}),
-      base::Minutes(1), 1);
+      kExpectedEngagementTime, 1);
 
   // Now do the same sequence in tablet mode.
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
   LockScreen();
 
-  FastForwardToLockScreenTimeout();
-  FastForwardTiny();
+  task_environment()->FastForwardBy(ambient_controller()
+                                        ->ambient_ui_model()
+                                        ->lock_screen_inactivity_timeout());
   ASSERT_TRUE(ambient_controller()->IsShown());
 
-  task_environment()->FastForwardBy(base::Minutes(1));
+  task_environment()->FastForwardBy(kExpectedEngagementTime);
 
   UnlockScreen();
   ASSERT_FALSE(ambient_controller()->IsShown());
 
   histogram_tester.ExpectTimeBucketCount(
-      "Ash.AmbientMode.EngagementTime.TabletMode", base::Minutes(1), 1);
+      "Ash.AmbientMode.EngagementTime.TabletMode", kExpectedEngagementTime, 1);
   histogram_tester.ExpectTimeBucketCount(
       base::StrCat({"Ash.AmbientMode.EngagementTime.", ToString(GetParam())}),
-      base::Minutes(1), 2);
+      kExpectedEngagementTime, 2);
 }
 
 TEST_P(AmbientControllerTestForAnyTheme, MetricsStartupTime) {
diff --git a/ash/components/arc/compat_mode/resize_util_unittest.cc b/ash/components/arc/compat_mode/resize_util_unittest.cc
index 7304be8..3cf11c0 100644
--- a/ash/components/arc/compat_mode/resize_util_unittest.cc
+++ b/ash/components/arc/compat_mode/resize_util_unittest.cc
@@ -24,6 +24,15 @@
   // ToastManager overrides:
   void Show(const ash::ToastData& data) override { called_show_ = true; }
   void Cancel(const std::string& id) override { called_cancel_ = true; }
+  bool MaybeToggleA11yHighlightOnActiveToastDismissButton(
+      const std::string& id) override {
+    return false;
+  }
+  bool MaybeActivateHighlightedDismissButtonOnActiveToast(
+      const std::string& id) override {
+    return false;
+  }
+  bool IsRunning(const std::string& id) const override { return false; }
 
   void ResetState() {
     called_show_ = false;
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index 008e44c..39442923 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -115,7 +115,7 @@
 // Controls whether to launch the animated screensaver (as opposed to the
 // existing photo slideshow) when entering ambient mode.
 const base::Feature kAmbientModeAnimationFeature{
-    "ChromeOSAmbientModeAnimation", base::FEATURE_DISABLED_BY_DEFAULT};
+    "ChromeOSAmbientModeAnimation", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether to allow Dev channel to use Prod server feature.
 const base::Feature kAmbientModeDevUseProdFeature{
@@ -1079,7 +1079,7 @@
 
 // Enables new notifications UI and grouped notifications.
 const base::Feature kNotificationsRefresh{"NotificationsRefresh",
-                                          base::FEATURE_DISABLED_BY_DEFAULT};
+                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Controls whether to enable on-device grammar check service.
 const base::Feature kOnDeviceGrammarCheck{"OnDeviceGrammarCheck",
@@ -1647,7 +1647,8 @@
 }
 
 bool IsAmbientModeAnimationEnabled() {
-  return base::FeatureList::IsEnabled(kAmbientModeAnimationFeature);
+  return base::FeatureList::IsEnabled(kAmbientModeAnimationFeature) &&
+         IsPersonalizationHubEnabled();
 }
 
 bool IsAmbientModeDevUseProdEnabled() {
@@ -1762,8 +1763,7 @@
 }
 
 bool IsDarkLightModeEnabled() {
-  return base::FeatureList::IsEnabled(kNotificationsRefresh) ||
-         chromeos::features::IsDarkLightModeEnabled();
+  return chromeos::features::IsDarkLightModeEnabled();
 }
 
 bool IsDemoModeSWAEnabled() {
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc
index 3f79d74..def3c9a 100644
--- a/ash/constants/ash_switches.cc
+++ b/ash/constants/ash_switches.cc
@@ -673,6 +673,10 @@
 // Specifies the user that the browser data migration should happen for.
 const char kBrowserDataMigrationForUser[] = "browser-data-migration-for-user";
 
+// Run move migration instead of copy. Passed with
+// `kBrowserDataMigrationForUser`.
+const char kBrowserDataMigrationMoveMode[] = "browser-data-migration-move-mode";
+
 // Force skip or force migration. Should only be used for testing.
 const char kForceBrowserDataMigrationForTesting[] =
     "force-browser-data-migration-for-testing";
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h
index 854ed04..ab02961 100644
--- a/ash/constants/ash_switches.h
+++ b/ash/constants/ash_switches.h
@@ -217,6 +217,8 @@
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kBrowserDataMigrationForUser[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
+extern const char kBrowserDataMigrationMoveMode[];
+COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kForceBrowserDataMigrationForTesting[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kMarketingOptInUrl[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kNaturalScrollDefault[];
diff --git a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
index 0ed62d2..711b0a823 100644
--- a/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
+++ b/ash/frame/caption_buttons/frame_caption_button_container_view_unittest.cc
@@ -105,6 +105,14 @@
     generator->ClickLeftButton();
     base::RunLoop().RunUntilIdle();
   }
+
+  void ClickFloatButton(FrameCaptionButtonContainerView::TestApi* testApi) {
+    ui::test::EventGenerator* generator = GetEventGenerator();
+    auto* float_button = testApi->float_button();
+    generator->MoveMouseTo(float_button->GetBoundsInScreen().CenterPoint());
+    generator->ClickLeftButton();
+    base::RunLoop().RunUntilIdle();
+  }
 };
 
 // Test float button requires kFloatWindow feature to be enabled during setup.
@@ -335,24 +343,18 @@
   container.Layout();
   FrameCaptionButtonContainerView::TestApi testApi(&container);
   FloatController* controller = Shell::Get()->float_controller();
-
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  generator->MoveMouseTo(
-      testApi.float_button()->GetBoundsInScreen().CenterPoint());
-  generator->ClickLeftButton();
-
+  ClickFloatButton(&testApi);
+  auto* window_state = WindowState::Get(widget->GetNativeWindow());
   // Check if window is floated.
   auto* window = widget->GetNativeWindow();
-  EXPECT_TRUE(window->GetProperty(chromeos::kWindowFloatTypeKey));
+  EXPECT_TRUE(window_state->IsFloated());
+  EXPECT_TRUE(window->GetProperty(chromeos::kWindowToggleFloatKey));
   EXPECT_TRUE(controller->IsFloated(window));
-
-  generator->MoveMouseTo(
-      testApi.float_button()->GetBoundsInScreen().CenterPoint());
-  generator->ClickLeftButton();
-
+  ClickFloatButton(&testApi);
   // Check if window is unfloated.
-  EXPECT_FALSE(window->GetProperty(chromeos::kWindowFloatTypeKey));
+  EXPECT_TRUE(window_state->IsNormalStateType());
   EXPECT_FALSE(controller->IsFloated(window));
+  EXPECT_FALSE(window->GetProperty(chromeos::kWindowToggleFloatKey));
 }
 
 }  // namespace ash
diff --git a/ash/metrics/user_metrics_recorder.cc b/ash/metrics/user_metrics_recorder.cc
index 91cae0d..3fa40787 100644
--- a/ash/metrics/user_metrics_recorder.cc
+++ b/ash/metrics/user_metrics_recorder.cc
@@ -44,6 +44,7 @@
   ACTIVE_WINDOW_STATE_TYPE_PINNED,
   ACTIVE_WINDOW_STATE_TYPE_TRUSTED_PINNED,
   ACTIVE_WINDOW_STATE_TYPE_PIP,
+  ACTIVE_WINDOW_STATE_TYPE_FLOATED,
   ACTIVE_WINDOW_STATE_TYPE_COUNT,
 };
 
@@ -72,6 +73,9 @@
       case WindowStateType::kPip:
         active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_PIP;
         break;
+      case WindowStateType::kFloated:
+        active_window_state_type = ACTIVE_WINDOW_STATE_TYPE_FLOATED;
+        break;
       case WindowStateType::kDefault:
       case WindowStateType::kNormal:
       case WindowStateType::kMinimized:
diff --git a/ash/public/cpp/system/toast_manager.h b/ash/public/cpp/system/toast_manager.h
index 9227f56d..0bf06eb8 100644
--- a/ash/public/cpp/system/toast_manager.h
+++ b/ash/public/cpp/system/toast_manager.h
@@ -25,6 +25,21 @@
   // Cancels a toast with the provided ID.
   virtual void Cancel(const std::string& id) = 0;
 
+  // Toggles highlight on the dismiss button for an active toast. Returns false
+  // if this is not possible or if the highlight has been removed from the
+  // button.
+  virtual bool MaybeToggleA11yHighlightOnActiveToastDismissButton(
+      const std::string& id) = 0;
+
+  // Activates the dismiss button on the active toast if there is a button and
+  // that button is highlighted. Returns false if either case is not true, or if
+  // there is no active toast.
+  virtual bool MaybeActivateHighlightedDismissButtonOnActiveToast(
+      const std::string& id) = 0;
+
+  // Tells if the toast with the provided ID is running.
+  virtual bool IsRunning(const std::string& id) const = 0;
+
  protected:
   ToastManager();
   virtual ~ToastManager();
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index cee433e..3e9e2c1 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -195,7 +195,8 @@
 }
 
 bool HomeButton::IsShowingAppList() const {
-  return controller_.is_showing_app_list();
+  return Shell::Get()->app_list_controller()->GetTargetVisibility(
+      GetDisplayId());
 }
 
 void HomeButton::HandleLocaleChange() {
diff --git a/ash/shelf/home_button_controller.cc b/ash/shelf/home_button_controller.cc
index d6c4602..17294c2 100644
--- a/ash/shelf/home_button_controller.cc
+++ b/ash/shelf/home_button_controller.cc
@@ -183,7 +183,6 @@
     views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::ACTIVATED,
                                                  nullptr);
   }
-  is_showing_app_list_ = true;
 }
 
 void HomeButtonController::OnAppListDismissed() {
@@ -195,8 +194,6 @@
     ink_drop->SnapToActivated();
   views::InkDrop::Get(button_)->AnimateToState(views::InkDropState::DEACTIVATED,
                                                nullptr);
-
-  is_showing_app_list_ = false;
 }
 
 void HomeButtonController::InitializeAssistantOverlay() {
diff --git a/ash/shelf/home_button_controller.h b/ash/shelf/home_button_controller.h
index 5e9e1b6f..6db20207 100644
--- a/ash/shelf/home_button_controller.h
+++ b/ash/shelf/home_button_controller.h
@@ -47,8 +47,6 @@
   // Whether the Assistant UI currently showing.
   bool IsAssistantVisible();
 
-  bool is_showing_app_list() const { return is_showing_app_list_; }
-
  private:
   // AppListControllerObserver:
   void OnAppListVisibilityWillChange(bool shown, int64_t display_id) override;
@@ -76,10 +74,6 @@
   // Initialize the Assistant overlay.
   void InitializeAssistantOverlay();
 
-  // True if the app list is currently showing for the button's display.
-  // This is useful because other app_list_visible functions aren't per-display.
-  bool is_showing_app_list_ = false;
-
   // The button that owns this controller.
   HomeButton* const button_;
 
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index d787721..8302678 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -863,11 +863,6 @@
   ShowIfHidden();
 }
 
-bool ShelfWidget::IsShowingAppList() const {
-  return navigation_widget()->GetHomeButton() &&
-         navigation_widget()->GetHomeButton()->IsShowingAppList();
-}
-
 bool ShelfWidget::IsShowingMenu() const {
   return hotseat_widget()->GetShelfView()->IsShowingMenu();
 }
diff --git a/ash/shelf/shelf_widget.h b/ash/shelf/shelf_widget.h
index 229f7251f..523ad5dc 100644
--- a/ash/shelf/shelf_widget.h
+++ b/ash/shelf/shelf_widget.h
@@ -83,7 +83,6 @@
   }
   void PostCreateShelf();
 
-  bool IsShowingAppList() const;
   bool IsShowingMenu() const;
 
   // Sets the focus cycler. Also adds the shelf to the cycle.
diff --git a/ash/style/system_toast_style.cc b/ash/style/system_toast_style.cc
index 9df39e1..15530d1 100644
--- a/ash/style/system_toast_style.cc
+++ b/ash/style/system_toast_style.cc
@@ -6,6 +6,8 @@
 
 #include <string>
 
+#include "ash/accessibility/accessibility_controller_impl.h"
+#include "ash/accessibility/scoped_a11y_override_window_setter.h"
 #include "ash/resources/vector_icons/vector_icons.h"
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
@@ -14,6 +16,7 @@
 #include "ash/system/toast/toast_overlay.h"
 #include "ash/wm/work_area_insets.h"
 #include "base/strings/strcat.h"
+#include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
 #include "ui/compositor/layer.h"
@@ -22,6 +25,7 @@
 #include "ui/gfx/text_elider.h"
 #include "ui/gfx/text_utils.h"
 #include "ui/views/background.h"
+#include "ui/views/controls/focus_ring.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/highlight_border.h"
@@ -108,7 +112,9 @@
 SystemToastStyle::SystemToastStyle(base::RepeatingClosure dismiss_callback,
                                    const std::u16string& text,
                                    const std::u16string& dismiss_text,
-                                   const bool is_managed) {
+                                   const bool is_managed)
+    : scoped_a11y_overrider_(
+          std::make_unique<ScopedA11yOverrideWindowSetter>()) {
   SetPaintToLayer();
   layer()->SetFillsBoundsOpaquely(false);
   layer()->SetBackgroundBlur(ColorProvider::kBackgroundBlurSigma);
@@ -171,6 +177,30 @@
 
 SystemToastStyle::~SystemToastStyle() = default;
 
+bool SystemToastStyle::ToggleA11yFocus() {
+  if (!button_ ||
+      !Shell::Get()->accessibility_controller()->spoken_feedback().enabled()) {
+    return false;
+  }
+
+  auto* focus_ring = views::FocusRing::Get(button_);
+  focus_ring->SetHasFocusPredicate([&](views::View* view) -> bool {
+    return is_dismiss_button_highlighted_;
+  });
+
+  is_dismiss_button_highlighted_ = !is_dismiss_button_highlighted_;
+  scoped_a11y_overrider_->MaybeUpdateA11yOverrideWindow(
+      is_dismiss_button_highlighted_ ? button_->GetWidget()->GetNativeWindow()
+                                     : nullptr);
+
+  if (is_dismiss_button_highlighted_)
+    button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
+
+  focus_ring->SetVisible(is_dismiss_button_highlighted_);
+  focus_ring->SchedulePaint();
+  return is_dismiss_button_highlighted_;
+}
+
 void SystemToastStyle::SetText(const std::u16string& text) {
   label_->SetText(text);
 }
diff --git a/ash/style/system_toast_style.h b/ash/style/system_toast_style.h
index 95cb89a..f8e1c9b 100644
--- a/ash/style/system_toast_style.h
+++ b/ash/style/system_toast_style.h
@@ -18,6 +18,8 @@
 
 namespace ash {
 
+class ScopedA11yOverrideWindowSetter;
+
 // A view that has rounded corner with label and button inside. The label shows
 // the information. The button inside is optional and has certain functionality
 // e.g. dismiss the view or retry. A managed icon will be put ahead of the label
@@ -36,6 +38,14 @@
   SystemToastStyle& operator=(const SystemToastStyle&) = delete;
   ~SystemToastStyle() override;
 
+  bool is_dismiss_button_highlighted() const {
+    return is_dismiss_button_highlighted_;
+  }
+
+  // Returns true if the toast has a dismiss button and was highlighted for
+  // accessibility, false otherwise.
+  bool ToggleA11yFocus();
+
   // Updates the toast label text.
   void SetText(const std::u16string& text);
 
@@ -48,6 +58,13 @@
   views::Label* label_ = nullptr;
   views::LabelButton* button_ = nullptr;
   views::ImageView* managed_icon_ = nullptr;
+
+  // Tells the toast if the dismiss button is already highlighted if one exists.
+  bool is_dismiss_button_highlighted_ = false;
+
+  // Updates the current a11y override window when the dismiss button is being
+  // highlighted.
+  std::unique_ptr<ScopedA11yOverrideWindowSetter> scoped_a11y_overrider_;
 };
 
 }  // namespace ash
diff --git a/ash/system/message_center/ash_notification_view.cc b/ash/system/message_center/ash_notification_view.cc
index 40e8d30..6c8ce9f 100644
--- a/ash/system/message_center/ash_notification_view.cc
+++ b/ash/system/message_center/ash_notification_view.cc
@@ -1184,8 +1184,13 @@
   NotificationViewBase::ToggleInlineSettings(event);
 
   if (is_grouped_parent_view_) {
-    grouped_notifications_scroll_view_->SetVisible(
-        !should_show_inline_settings);
+    if (shown_in_popup_) {
+      grouped_notifications_scroll_view_->SetVisible(
+          !should_show_inline_settings);
+    } else {
+      grouped_notifications_container_->SetVisible(
+          !should_show_inline_settings);
+    }
   } else {
     // In settings UI, we only show the app icon and header row along with the
     // inline settings UI.
@@ -1457,9 +1462,10 @@
       grouped_notifications_container_->GetIndexOf(to_be_removed);
   grouped_notifications_container_->RemoveChildViewT(to_be_removed).reset();
 
-  message_center_utils::GetActiveNotificationViewControllerForNotificationView(
-      this)
-      ->AnimateResize();
+  auto* notification_view_controller = message_center_utils::
+      GetActiveNotificationViewControllerForNotificationView(this);
+  if (notification_view_controller)
+    notification_view_controller->AnimateResize();
 
   if (shown_in_popup_) {
     grouped_notifications_scroll_view_->Layout();
diff --git a/ash/system/message_center/message_center_utils.cc b/ash/system/message_center/message_center_utils.cc
index 5bac163..72b211f 100644
--- a/ash/system/message_center/message_center_utils.cc
+++ b/ash/system/message_center/message_center_utils.cc
@@ -83,8 +83,9 @@
 GetActiveNotificationViewControllerForDisplay(int64_t display_id) {
   RootWindowController* root_window_controller =
       Shell::GetRootWindowControllerWithDisplayId(display_id);
-  if (!root_window_controller)
+  if (!root_window_controller || !root_window_controller->GetStatusAreaWidget())
     return nullptr;
+
   return root_window_controller->GetStatusAreaWidget()
       ->unified_system_tray()
       ->GetNotificationGroupingController()
diff --git a/ash/system/message_center/notification_grouping_controller.cc b/ash/system/message_center/notification_grouping_controller.cc
index 8429025..b9133fd 100644
--- a/ash/system/message_center/notification_grouping_controller.cc
+++ b/ash/system/message_center/notification_grouping_controller.cc
@@ -145,8 +145,10 @@
              ->FindNotificationById(notification_id)
              ->group_parent());
   MessageView* parent_view =
-      GetActiveNotificationViewController()->GetMessageViewForNotificationId(
-          notification_id);
+      GetActiveNotificationViewController()
+          ? GetActiveNotificationViewController()
+                ->GetMessageViewForNotificationId(notification_id)
+          : nullptr;
 
   // TODO(crbug/1277765) Need this check to fix crbug/1275765. However, this
   // should not be necessary if the message center bubble is initialized
@@ -193,8 +195,10 @@
   Notification* notification =
       message_center->FindNotificationById(notification_id);
   MessageView* parent_view =
-      GetActiveNotificationViewController()->GetMessageViewForNotificationId(
-          parent_id);
+      GetActiveNotificationViewController()
+          ? GetActiveNotificationViewController()
+                ->GetMessageViewForNotificationId(parent_id)
+          : nullptr;
   if (parent_view)
     parent_view->AddGroupNotification(*notification);
   else
@@ -258,9 +262,10 @@
   metrics_utils::LogGroupNotificationAddedType(
       metrics_utils::GroupNotificationType::GROUP_CHILD);
 
-  auto* parent_view =
-      GetActiveNotificationViewController()->GetMessageViewForNotificationId(
-          new_parent_id);
+  auto* parent_view = GetActiveNotificationViewController()
+                          ? GetActiveNotificationViewController()
+                                ->GetMessageViewForNotificationId(new_parent_id)
+                          : nullptr;
   if (parent_view) {
     parent_view->UpdateWithNotification(*new_parent_notification);
     // Grouped notifications should start off in the collapsed state.
@@ -311,7 +316,8 @@
   // in a grouped notification.
   auto grouped_notifications =
       grouped_notification_list_->GetGroupedNotificationsForParent(parent_id);
-  if (GetActiveNotificationViewController()->GetMessageViewForNotificationId(
+  if (GetActiveNotificationViewController() &&
+      GetActiveNotificationViewController()->GetMessageViewForNotificationId(
           parent_id) &&
       grouped_notifications.size() == 1) {
     MessageCenter::Get()->RemoveNotification(parent_id, true);
@@ -355,9 +361,12 @@
       message_center->FindParentNotification(notification);
   std::string parent_id = parent_notification->id();
 
-  auto* parent_view = static_cast<AshNotificationView*>(
-      GetActiveNotificationViewController()->GetMessageViewForNotificationId(
-          parent_id));
+  auto* parent_view =
+      GetActiveNotificationViewController()
+          ? static_cast<AshNotificationView*>(
+                GetActiveNotificationViewController()
+                    ->GetMessageViewForNotificationId(parent_id))
+          : nullptr;
 
   // If we are creating a new notification group for this `notifier_id`,
   // we must create a copy of the designated parent notification and
diff --git a/ash/system/network/network_list_view_controller_impl.cc b/ash/system/network/network_list_view_controller_impl.cc
index 80468a2..b5d113b4 100644
--- a/ash/system/network/network_list_view_controller_impl.cc
+++ b/ash/system/network/network_list_view_controller_impl.cc
@@ -237,6 +237,9 @@
   network_detailed_network_view()->network_list()->ReorderChildView(
       wifi_header_view_, index++);
 
+  index = CreateItemViewsIfMissingAndReorder(NetworkType::kWiFi, index,
+                                             networks, &previous_network_views);
+
   // Remaining views in |previous_network_views| are no longer needed
   // and should be deleted.
   for (const auto& id_and_view : previous_network_views) {
diff --git a/ash/system/network/network_list_view_controller_impl.h b/ash/system/network/network_list_view_controller_impl.h
index afd4e8e..9dcc79e 100644
--- a/ash/system/network/network_list_view_controller_impl.h
+++ b/ash/system/network/network_list_view_controller_impl.h
@@ -99,7 +99,7 @@
   bool ShouldMobileDataSectionBeShown();
 
   // Creates if missing and adds a Mobile or Wifi separator to the view.
-  // Also reorders seperator view in network list. A reference to the
+  // Also reorders separator view in network list. A reference to the
   // separator is captured in |*separator_view|.
   int CreateSeparatorIfMissingAndReorder(int index,
                                          views::Separator** separator_view);
diff --git a/ash/system/network/network_list_view_controller_unittest.cc b/ash/system/network/network_list_view_controller_unittest.cc
index 9ffd02d..7f1a7d4 100644
--- a/ash/system/network/network_list_view_controller_unittest.cc
+++ b/ash/system/network/network_list_view_controller_unittest.cc
@@ -74,6 +74,7 @@
 const char kVpnDevicePath[] = "device/vpn";
 
 const char kWifiName[] = "wifi";
+const char kWifiName2[] = "wifi_2";
 const char kWifiDevicePath[] = "device/wifi";
 
 const char kTestEuiccBasePath[] = "/org/chromium/Hermes/Euicc/";
@@ -241,44 +242,48 @@
         mojo::Clone(networks));
   }
 
-  // Checks that network list items are in the right order. This function
-  // assumes that Mobile and Wifi devices are present and enabled.
-  void CheckNetworkListOrdering(size_t ethernet_network_count,
-                                size_t mobile_network_count) {
-    // TODO(tjohnsonkanu): add  WiFi networks.
-    EXPECT_NE(nullptr, GetMobileSubHeader());
+  // Checks that network list items are in the right order. Wifi section
+  // is always shown.
+  void CheckNetworkListOrdering(int ethernet_network_count,
+                                int mobile_network_count,
+                                int wifi_network_count) {
     EXPECT_NE(nullptr, GetWifiSubHeader());
 
     size_t index = 0;
 
     // Expect that the view at |index| is a network item, and that it is an
     // ethernet network.
-    for (int i = 0; i < static_cast<int>(ethernet_network_count); i++) {
+    for (int i = 0; i < ethernet_network_count; i++) {
       CheckNetworkListItem(NetworkType::kEthernet, index++,
                            /*guid=*/absl::nullopt);
     }
 
-    // Mobile data section.
-    if (index > 0) {
-      // Expect that the mobile network separator exists.
-      EXPECT_NE(nullptr, GetMobileSeparator());
-      EXPECT_EQ(network_list()->children().at(index++), GetMobileSeparator());
-      EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader());
-    } else {
-      EXPECT_EQ(nullptr, GetMobileSeparator());
-      EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader());
-    }
+    // Mobile data section. If |mobile_network_count| is equal to -1
+    // Mobile device is not available.
+    if (mobile_network_count != -1) {
+      EXPECT_NE(nullptr, GetMobileSubHeader());
+      if (index > 0) {
+        // Expect that the mobile network separator exists.
+        EXPECT_NE(nullptr, GetMobileSeparator());
+        EXPECT_EQ(network_list()->children().at(index++), GetMobileSeparator());
+        EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader());
+      } else {
+        EXPECT_EQ(nullptr, GetMobileSeparator());
+        EXPECT_EQ(network_list()->children().at(index++), GetMobileSubHeader());
+      }
 
-    for (int i = 0; i < static_cast<int>(mobile_network_count); i++) {
-      CheckNetworkListItem(NetworkType::kMobile, index, /*guid=*/absl::nullopt);
-      EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(),
-                   kNetworkListNetworkItemView);
-    }
+      for (int i = 0; i < mobile_network_count; i++) {
+        CheckNetworkListItem(NetworkType::kMobile, index,
+                             /*guid=*/absl::nullopt);
+        EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(),
+                     kNetworkListNetworkItemView);
+      }
 
-    if (!mobile_network_count) {
-      // No mobile networks message is shown.
-      EXPECT_NE(nullptr, GetMobileStatusMessage());
-      index++;
+      if (!mobile_network_count) {
+        // No mobile networks message is shown.
+        EXPECT_NE(nullptr, GetMobileStatusMessage());
+        index++;
+      }
     }
 
     // Wifi section.
@@ -291,6 +296,12 @@
       EXPECT_EQ(nullptr, GetWifiSeparator());
       EXPECT_EQ(network_list()->children().at(index++), GetWifiSubHeader());
     }
+
+    for (int i = 0; i < wifi_network_count; i++) {
+      CheckNetworkListItem(NetworkType::kWiFi, index, /*guid=*/absl::nullopt);
+      EXPECT_STREQ(network_list()->children().at(index++)->GetClassName(),
+                   kNetworkListNetworkItemView);
+    }
   }
 
   void CheckNetworkListItem(NetworkType type,
@@ -582,8 +593,9 @@
   SetupCellular();
   AddWifiDevice();
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/0u,
-                           /*mobile_network_count=*/0u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/0,
+                           /*wifi_network_count=*/0);
 
   std::vector<NetworkStatePropertiesPtr> networks;
 
@@ -593,8 +605,9 @@
   networks.push_back(std::move(cellular_network));
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/0u,
-                           /*mobile_network_count=*/1u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kCellular, /*index=*/1u,
                        /*guid=*/kCellularName);
 
@@ -603,8 +616,9 @@
   networks.push_back(std::move(cellular_network));
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/0u,
-                           /*mobile_network_count=*/2u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/2,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kCellular, /*index=*/2u,
                        /*guid=*/kCellularName2);
 
@@ -612,8 +626,9 @@
   networks.front()->connection_state = ConnectionStateType::kNotConnected;
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/0u,
-                           /*mobile_network_count=*/2u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/2,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kCellular, /*index=*/1u,
                        /*guid=*/kCellularName);
   CheckNetworkListItem(NetworkType::kCellular, /*index=*/2u,
@@ -627,15 +642,14 @@
   networks.push_back(std::move(tether_network));
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/0u,
-                           /*mobile_network_count=*/1u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kTether, /*index=*/1u,
                        /*guid=*/kTetherName);
 }
 
 TEST_F(NetworkListViewControllerTest, HasCorrectEthernetNetworkList) {
-  AddEuicc();
-  SetupCellular();
   std::vector<NetworkStatePropertiesPtr> networks;
 
   NetworkStatePropertiesPtr ethernet_network =
@@ -644,19 +658,23 @@
   networks.push_back(std::move(ethernet_network));
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/1u,
-                           /*mobile_network_count=*/0u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/1,
+                           /*mobile_network_count=*/-1,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kEthernet, /*index=*/0u,
                        /*guid=*/kEthernet);
 
   // Add mobile network.
+  AddEuicc();
+  SetupCellular();
   NetworkStatePropertiesPtr cellular_network =
       CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular,
                                         ConnectionStateType::kConnected);
   networks.push_back(std::move(cellular_network));
   UpdateNetworkList(networks);
-  CheckNetworkListOrdering(/*ethernet_network_count=*/1u,
-                           /*mobile_network_count=*/1u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/1,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/0);
 
   // Mobile list item will be at index 3 after ethernet, separator and header.
   CheckNetworkListItem(NetworkType::kCellular, /*index=*/3u,
@@ -667,8 +685,9 @@
   networks.push_back(std::move(ethernet_network));
   UpdateNetworkList(networks);
 
-  CheckNetworkListOrdering(/*ethernet_network_count=*/2u,
-                           /*mobile_network_count=*/1u);
+  CheckNetworkListOrdering(/*ethernet_network_count=*/2,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/0);
   CheckNetworkListItem(NetworkType::kEthernet, /*index=*/0u,
                        /*guid=*/kEthernet);
   CheckNetworkListItem(NetworkType::kEthernet, /*index=*/1u,
@@ -679,6 +698,52 @@
                        /*guid=*/kCellularName);
 }
 
+TEST_F(NetworkListViewControllerTest, HasCorrectWifiNetworkList) {
+  std::vector<NetworkStatePropertiesPtr> networks;
+
+  // Add Wifi network.
+  NetworkStatePropertiesPtr wifi_network = CreateStandaloneNetworkProperties(
+      kWifiName, NetworkType::kWiFi, ConnectionStateType::kNotConnected);
+  networks.push_back(std::move(wifi_network));
+  UpdateNetworkList(networks);
+
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/-1,
+                           /*wifi_network_count=*/1);
+
+  // Wifi list item will be at index 1 after Wifi header.
+  CheckNetworkListItem(NetworkType::kWiFi, /*index=*/1u, /*guid=*/kWifiName);
+
+  // Add mobile network.
+  AddEuicc();
+  SetupCellular();
+  NetworkStatePropertiesPtr cellular_network =
+      CreateStandaloneNetworkProperties(kCellularName, NetworkType::kCellular,
+                                        ConnectionStateType::kConnected);
+  networks.push_back(std::move(cellular_network));
+  UpdateNetworkList(networks);
+
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/1);
+
+  // Wifi list item be at index 4 after Mobile header, Mobile network
+  // item, Wifi separator and header.
+  CheckNetworkListItem(NetworkType::kWiFi, /*index=*/4u, /*guid=*/kWifiName);
+
+  // Add a second Wifi network.
+  wifi_network = CreateStandaloneNetworkProperties(
+      kWifiName2, NetworkType::kWiFi, ConnectionStateType::kNotConnected);
+  networks.push_back(std::move(wifi_network));
+  UpdateNetworkList(networks);
+
+  CheckNetworkListOrdering(/*ethernet_network_count=*/0,
+                           /*mobile_network_count=*/1,
+                           /*wifi_network_count=*/2);
+  CheckNetworkListItem(NetworkType::kWiFi, /*index=*/4u, /*guid=*/kWifiName);
+  CheckNetworkListItem(NetworkType::kWiFi, /*index=*/5u, /*guid=*/kWifiName2);
+}
+
 TEST_F(NetworkListViewControllerTest,
        CellularStatusMessageAndToggleButtonState) {
   EXPECT_EQ(nullptr, GetMobileStatusMessage());
diff --git a/ash/system/time/calendar_event_list_item_view.cc b/ash/system/time/calendar_event_list_item_view.cc
index c1f5f44..c2d6bd7 100644
--- a/ash/system/time/calendar_event_list_item_view.cc
+++ b/ash/system/time/calendar_event_list_item_view.cc
@@ -34,6 +34,9 @@
 namespace ash {
 namespace {
 
+// The paddings for `CalendarEventListViewItem`.
+constexpr auto kEventListItemInsets = gfx::Insets::VH(0, 20);
+
 // Paddings in this view.
 constexpr int kEntryHorizontalPadding = 20;
 
@@ -146,6 +149,7 @@
       end_time_string, calendar_utils::GetTimeZone(start_time),
       base::UTF8ToUTF16(event.summary())));
   SetFocusBehavior(FocusBehavior::ALWAYS);
+  SetBorder(views::CreateEmptyBorder(kEventListItemInsets));
   summary_->SetText(event.summary().empty()
                         ? l10n_util::GetStringUTF16(IDS_ASH_CALENDAR_NO_TITLE)
                         : base::UTF8ToUTF16(event.summary()));
diff --git a/ash/system/time/calendar_event_list_view.cc b/ash/system/time/calendar_event_list_view.cc
index e271971f..decd0c4 100644
--- a/ash/system/time/calendar_event_list_view.cc
+++ b/ash/system/time/calendar_event_list_view.cc
@@ -39,13 +39,13 @@
 constexpr gfx::Insets kCloseButtonContainerInsets{15};
 
 // The paddings in `CalendarEventListView`.
-constexpr auto kContentInsets = gfx::Insets::TLBR(0, 20, 20, 20);
+constexpr auto kContentInsets = gfx::Insets::TLBR(0, 0, 20, 0);
 
 // The insets for `CalendarEmptyEventListView` label.
 constexpr auto kOpenGoogleCalendarInsets = gfx::Insets::VH(6, 16);
 
 // The insets for `CalendarEmptyEventListView`.
-constexpr auto kOpenGoogleCalendarContainerInsets = gfx::Insets::VH(20, 60);
+constexpr auto kOpenGoogleCalendarContainerInsets = gfx::Insets::VH(20, 80);
 
 // Border thickness for `CalendarEmptyEventListView`.
 constexpr int kOpenGoogleCalendarBorderThickness = 1;
diff --git a/ash/system/toast/toast_manager_impl.cc b/ash/system/toast/toast_manager_impl.cc
index 1b34568..9c4cffb1 100644
--- a/ash/system/toast/toast_manager_impl.cc
+++ b/ash/system/toast/toast_manager_impl.cc
@@ -65,6 +65,22 @@
     queue_.erase(cancelled_toast);
 }
 
+bool ToastManagerImpl::MaybeToggleA11yHighlightOnActiveToastDismissButton(
+    const std::string& id) {
+  DCHECK(IsRunning(id));
+  return overlay_ && overlay_->MaybeToggleA11yHighlightOnDismissButton();
+}
+
+bool ToastManagerImpl::MaybeActivateHighlightedDismissButtonOnActiveToast(
+    const std::string& id) {
+  DCHECK(IsRunning(id));
+  return overlay_ && overlay_->MaybeActivateHighlightedDismissButton();
+}
+
+bool ToastManagerImpl::IsRunning(const std::string& id) const {
+  return overlay_ && current_toast_data_ && current_toast_data_->id == id;
+}
+
 void ToastManagerImpl::OnClosed() {
   overlay_.reset();
   current_toast_data_.reset();
@@ -76,10 +92,6 @@
     ShowLatest();
 }
 
-bool ToastManagerImpl::IsRunning(const std::string& id) const {
-  return overlay_ && current_toast_data_ && current_toast_data_->id == id;
-}
-
 void ToastManagerImpl::ShowLatest() {
   DCHECK(!overlay_);
   DCHECK(!current_toast_data_);
diff --git a/ash/system/toast/toast_manager_impl.h b/ash/system/toast/toast_manager_impl.h
index a41dacc..cdebe23 100644
--- a/ash/system/toast/toast_manager_impl.h
+++ b/ash/system/toast/toast_manager_impl.h
@@ -33,6 +33,11 @@
   // ToastManager overrides:
   void Show(const ToastData& data) override;
   void Cancel(const std::string& id) override;
+  bool MaybeToggleA11yHighlightOnActiveToastDismissButton(
+      const std::string& id) override;
+  bool MaybeActivateHighlightedDismissButtonOnActiveToast(
+      const std::string& id) override;
+  bool IsRunning(const std::string& id) const override;
 
   // ToastOverlay::Delegate overrides:
   void OnClosed() override;
@@ -46,9 +51,6 @@
   friend class AutoConnectNotifierTest;
   friend class DesksTestApi;
 
-  // Tells if the toast with the provided ID is running.
-  bool IsRunning(const std::string& id) const;
-
   void ShowLatest();
   void OnDurationPassed(int toast_number);
 
diff --git a/ash/system/toast/toast_overlay.cc b/ash/system/toast/toast_overlay.cc
index a9d02a2..f3c30735 100644
--- a/ash/system/toast/toast_overlay.cc
+++ b/ash/system/toast/toast_overlay.cc
@@ -178,6 +178,18 @@
   return text_;
 }
 
+bool ToastOverlay::MaybeToggleA11yHighlightOnDismissButton() {
+  return overlay_view_->ToggleA11yFocus();
+}
+
+bool ToastOverlay::MaybeActivateHighlightedDismissButton() {
+  if (!overlay_view_->is_dismiss_button_highlighted())
+    return false;
+
+  OnButtonClicked();
+  return true;
+}
+
 gfx::Rect ToastOverlay::CalculateOverlayBounds() {
   // If the native window has not been initialized, as in the first call, get
   // the default root window. Otherwise get the window for this overlay_widget
diff --git a/ash/system/toast/toast_overlay.h b/ash/system/toast/toast_overlay.h
index fdfaebb0..e0b9166 100644
--- a/ash/system/toast/toast_overlay.h
+++ b/ash/system/toast/toast_overlay.h
@@ -71,6 +71,14 @@
 
   const std::u16string GetText();
 
+  // Returns true if the toast has a button and it can be highlighted for
+  // accessibility, false otherwise.
+  bool MaybeToggleA11yHighlightOnDismissButton();
+
+  // Activates the dismiss button in `overlay_view_` if it is highlighted.
+  // Returns false if `is_dismiss_button_highlighted_` is false.
+  bool MaybeActivateHighlightedDismissButton();
+
  private:
   friend class ToastManagerImplTest;
   friend class DesksTestApi;
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc
index c729a75..16a29d2 100644
--- a/ash/system/unified/unified_system_tray.cc
+++ b/ash/system/unified/unified_system_tray.cc
@@ -103,7 +103,7 @@
 
  private:
   std::unique_ptr<MessageCenterUiController> const ui_controller_;
-  std::unique_ptr<AshMessagePopupCollection> const message_popup_collection_;
+  std::unique_ptr<AshMessagePopupCollection> message_popup_collection_;
 
   UnifiedSystemTray* const owner_;
 
@@ -131,7 +131,12 @@
                   owner->shelf()->GetStatusAreaWidget()->GetNativeWindow()));
 }
 
-UnifiedSystemTray::UiDelegate::~UiDelegate() = default;
+UnifiedSystemTray::UiDelegate::~UiDelegate() {
+  // We need to destruct `message_popup_collection_` before
+  // `grouping_controller_` to prevent a msan failure, so explicitly delete
+  // it here.
+  message_popup_collection_.reset();
+}
 
 void UnifiedSystemTray::UiDelegate::OnMessageCenterContentsChanged() {
   owner_->UpdateNotificationInternal();
@@ -247,6 +252,10 @@
   Shell::Get()->RemoveShellObserver(this);
 
   DestroyBubbles();
+
+  // We need to destruct `ui_delegate_` before `timer_` to prevent a msan
+  // failure, so explicitly delete it here.
+  ui_delegate_.reset();
 }
 
 void UnifiedSystemTray::AddObserver(Observer* observer) {
@@ -669,11 +678,21 @@
 }
 
 AshMessagePopupCollection* UnifiedSystemTray::GetMessagePopupCollection() {
+  // We need a check here since this function might be called when UiDelegate's
+  // dtor is triggered. In that case, the unique_ptr `ui_delegate_` is null even
+  // though the UiDelegate object is still in the middle of dtor process.
+  if (!ui_delegate_)
+    return nullptr;
   return ui_delegate_->message_popup_collection();
 }
 
 NotificationGroupingController*
 UnifiedSystemTray::GetNotificationGroupingController() {
+  // We need a check here since this function might be called when UiDelegate's
+  // dtor is triggered. In that case, the unique_ptr `ui_delegate_` is null even
+  // though the UiDelegate object is still in the middle of dtor process.
+  if (!ui_delegate_)
+    return nullptr;
   return ui_delegate_->grouping_controller();
 }
 
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h
index 4935f6e..906aca1 100644
--- a/ash/system/unified/unified_system_tray.h
+++ b/ash/system/unified/unified_system_tray.h
@@ -260,7 +260,7 @@
   // removing bubble related observers.
   void DestroyBubbles();
 
-  const std::unique_ptr<UiDelegate> ui_delegate_;
+  std::unique_ptr<UiDelegate> ui_delegate_;
 
   std::unique_ptr<UnifiedSystemTrayBubble> bubble_;
 
diff --git a/ash/test/ash_pixel_diff_test_base.cc b/ash/test/ash_pixel_diff_test_base.cc
index 39e315f2..fa22e51 100644
--- a/ash/test/ash_pixel_diff_test_base.cc
+++ b/ash/test/ash_pixel_diff_test_base.cc
@@ -4,7 +4,9 @@
 
 #include "ash/test/ash_pixel_diff_test_base.h"
 
+#include "ash/constants/ash_features.h"
 #include "ash/shell.h"
+#include "ash/style/ash_color_provider.h"
 #include "ash/system/power/power_status.h"
 #include "ash/wallpaper/wallpaper_controller_impl.h"
 #include "base/command_line.h"
@@ -90,6 +92,13 @@
 
   SimulateUserLogin(kAccountId_);
 
+  // If the dark/light mode feature is enabled, ensure to use the dark mode.
+  if (features::IsDarkLightModeEnabled()) {
+    auto* color_provider = AshColorProvider::Get();
+    if (!color_provider->IsDarkModeEnabled())
+      color_provider->ToggleColorMode();
+  }
+
   // Set variable UI components in explicit ways to stabilize screenshots.
   SetWallPaper();
   SetBatteryState();
diff --git a/ash/test/demo_ash_pixel_diff_test.cc b/ash/test/demo_ash_pixel_diff_test.cc
new file mode 100644
index 0000000..3e9aae42
--- /dev/null
+++ b/ash/test/demo_ash_pixel_diff_test.cc
@@ -0,0 +1,28 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/test/ash_pixel_diff_test_base.h"
+
+namespace ash {
+
+class DemoAshPixelDiffTest : public AshPixelDiffTestBase {
+ public:
+  DemoAshPixelDiffTest() = default;
+  DemoAshPixelDiffTest(const DemoAshPixelDiffTest&) = delete;
+  DemoAshPixelDiffTest& operator=(const DemoAshPixelDiffTest&) = delete;
+  ~DemoAshPixelDiffTest() override = default;
+
+  // AshPixelDiffTestBase:
+  void SetUp() override {
+    AshPixelDiffTestBase::SetUp();
+    pixel_diff()->Init(/*screenshot_prefix=*/"ash_demo_test");
+  }
+};
+
+// Verifies the primary display UI right after the ash pixel test sets up.
+TEST_F(DemoAshPixelDiffTest, VerifyDefaultPrimaryDisplay) {
+  EXPECT_TRUE(ComparePrimaryFullScreen("primary_display"));
+}
+
+}  // namespace ash
diff --git a/ash/webui/common/resources/BUILD.gn b/ash/webui/common/resources/BUILD.gn
index 563da69..2d46bcd2 100644
--- a/ash/webui/common/resources/BUILD.gn
+++ b/ash/webui/common/resources/BUILD.gn
@@ -34,7 +34,7 @@
     "mojo_utils.js",
   ]
   input_files_base_dir = rebase_path(".", "//")
-  deps = [ ":preprocess_generated" ]
+  public_deps = [ ":preprocess_generated" ]
   manifest_files = [ "$target_gen_dir/$preprocessed_gen_manifest" ]
   grd_prefix = "ash_common"
   out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp"
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc
index 76cd412..be6958e9 100644
--- a/ash/webui/personalization_app/personalization_app_ui.cc
+++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -262,6 +262,9 @@
   source->AddBoolean("isPersonalizationHubEnabled",
                      features::IsPersonalizationHubEnabled());
 
+  source->AddBoolean("isAmbientModeAnimationEnabled",
+                     features::IsAmbientModeAnimationEnabled());
+
   source->AddBoolean("isDarkLightModeEnabled",
                      features::IsDarkLightModeEnabled());
 
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
index 2fb3f4a0..a9aece8 100644
--- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
+++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
@@ -205,7 +205,7 @@
                 is-google-photos>
           </template>
         </div>
-        <h2 id="textContainer" class="preview-text-container album-info-mainpage album-info-subpage"
+        <h3 id="textContainer" class="preview-text-container album-info-mainpage album-info-subpage"
             aria-label$="[[getPreviewTextAriaLabel_(firstPreviewAlbum_, topicSource_, previewAlbums_)]]">
           <span id="currentlySet" class="currently-set-text" aria-hidden="true">
             $i18n{currentlySet}
@@ -219,7 +219,7 @@
           <span id="albumDescription" aria-hidden="true">
             [[getAlbumDescription_(topicSource_, previewAlbums_)]]
           </span>
-        </h2>
+        </h3>
         <div id="collageContainer" class$="[[getCollageContainerClass_(collageImages_)]]" aria-hidden="true">
           <template is="dom-repeat" items="[[collageImages_]]">
             <img class="collage-item" is="cr-auto-img"
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
index 97252c0..c5566c1 100644
--- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
+++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.html
@@ -177,8 +177,11 @@
           </div>
         </template>
         <template is="dom-if" if="[[!loadingSettings_]]">
-          <animation-theme-list selected-animation-theme="[[animationTheme_]]">
-          </animation-theme-list>
+          <template is="dom-if" if="[[isAmbientModeAnimationEnabled_]]">
+            <animation-theme-list
+                selected-animation-theme="[[animationTheme_]]">
+            </animation-theme-list>
+          </template>
           <topic-source-list selected-topic-source="[[topicSource_]]"
               has-google-photos-albums="[[hasGooglePhotosAlbums_(albums_)]]">
           </topic-source-list>
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts
index 9add348..fe176a5 100644
--- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_subpage_element.ts
@@ -16,6 +16,7 @@
 import './topic_source_list_element.js';
 
 import {assert} from 'chrome://resources/js/assert_ts.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {AmbientModeAlbum, AnimationTheme, TemperatureUnit, TopicSource} from '../personalization_app.mojom-webui.js';
 import {isAmbientModeAllowed, Paths} from '../personalization_router_element.js';
@@ -41,10 +42,20 @@
     return {
       path: Paths,
       queryParams: Object,
+      isAmbientModeAnimationEnabled_: {
+        type: Boolean,
+        value() {
+          return loadTimeData.getBoolean('isAmbientModeAnimationEnabled');
+        }
+      },
       albums_: {
         type: Array,
         value: null,
       },
+      animationTheme_: {
+        type: Object,
+        value: null,
+      },
       ambientModeEnabled_: Boolean,
       temperatureUnit_: Number,
       topicSource_: Number,
@@ -58,6 +69,7 @@
 
   path: Paths;
   queryParams: Record<string, string>;
+  private isAmbientModeAnimationEnabled_: boolean;
   private albums_: AmbientModeAlbum[]|null = null;
   private ambientModeEnabled_: boolean|null = null;
   private animationTheme_: AnimationTheme|null = null;
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html
index b106001..4d4515712 100644
--- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html
+++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_weather_element.html
@@ -11,8 +11,7 @@
   }
 </style>
 <div id="weatherDiv">
-  <h3 id="weatherTitle" class="ambient-subpage-element-title"
-      aria-hidden="true">
+  <h3 id="weatherTitle" class="ambient-subpage-element-title">
     $i18n{ambientModeWeatherTitle}
   </h3>
   <div class="weather-unit-list">
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html
index 9313c15..84984ed 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html
+++ b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html
@@ -35,7 +35,7 @@
     margin-inline-end: -18px;
   }
 
-  #ambientLabel > p {
+  #ambientLabel > h2 {
     color: var(--cros-text-color-primary);
     font: var(--personalization-app-label-font);
     margin: 14px 0;
@@ -53,7 +53,9 @@
     <template is="dom-if" if="[[isAmbientModeAllowed_()]]">
       <ambient-preview clickable="[[clickable_]]" main-page>
         <div id="ambientLabel">
-          <p on-click="onClickAmbientSubpageLink_" class="clickable">$i18n{screensaverLabel}</p>
+          <h2 on-click="onClickAmbientSubpageLink_" class="clickable">
+            $i18n{screensaverLabel}
+          </h2>
           <cr-icon-button id="ambientSubpageLink"
                 iron-icon="cr:chevron-right"
                 on-click="onClickAmbientSubpageLink_"
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html b/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html
index a5ec3dd..fe5c3e0 100644
--- a/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html
+++ b/ash/webui/personalization_app/resources/trusted/personalization_theme_element.html
@@ -1,5 +1,5 @@
 <style include="cros-button-style">
-  #themeLabel > p {
+  #themeLabel > h2 {
     color: var(--cros-text-color-primary);
     font: var(--personalization-app-label-font);
   }
@@ -44,7 +44,7 @@
 </style>
 <div id="container">
   <div id="themeLabel">
-    <p>$i18n{themeLabel}</p>
+    <h2>$i18n{themeLabel}</h2>
   </div>
   <iron-a11y-keys id="keys" keys="left right" on-keys-pressed="onKeysPress_">
   </iron-a11y-keys>
diff --git a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html
index 6bdfab2..5c4f2344 100644
--- a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html
+++ b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.html
@@ -43,7 +43,7 @@
     margin: 0;
   }
 
-  #infoContainer > p {
+  #infoContainer > h2 {
     color: var(--cros-text-color-primary);
     font: 400 22px/28px var(--cros-font-family-google-sans);
   }
@@ -54,6 +54,7 @@
     display: flex;
     flex-flow: row nowrap;
     padding-top: 4px;
+    text-decoration: none;
     width: fit-content;
   }
 
@@ -61,7 +62,7 @@
     outline: 2px solid var(--cros-focus-ring-color);
   }
 
-  #emailContainer > p {
+  #emailContainer > span {
     color: var(--cros-link-color);
     font: var(--cros-body-2-font);
     margin: 0;
@@ -168,13 +169,12 @@
   </div>
   <div id="infoContainer">
     <template is="dom-if" if="[[info_]]">
-      <p id="name">[[info_.name]]</p>
-      <div id="emailContainer" tabindex="0" on-click="onClickUserEmail_"
-          on-keypress="onClickUserEmail_" role="link"
+      <h2 id="name">[[info_.name]]</h2>
+      <a id="emailContainer" href="chrome://os-settings/accountManager" target="_blank"
           aria-description="$i18n{ariaLabelGoToAccountSettings}">
-        <p id="email">[[info_.email]]</p>
+        <span id="email">[[info_.email]]</span>
         <iron-icon icon="cr:open-in-new"></iron-icon>
-      </div>
+      </a>
     </template>
   </div>
 </div>
diff --git a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts
index a23399b..f75c36c2 100644
--- a/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/user/user_preview_element.ts
@@ -88,10 +88,6 @@
     initializeUserData(getUserProvider(), this.getStore());
   }
 
-  private onClickUserEmail_() {
-    window.open('chrome://os-settings/accountManager');
-  }
-
   private onClickUserSubpageLink_() {
     PersonalizationRouter.instance().goToRoute(Paths.USER);
   }
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
index 5825cc92..3754a36 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
@@ -22,12 +22,17 @@
     grid-template-rows: auto minmax(158px, 220px) 20px 1fr 24px;
   }
 
-  #wallpaperLabel > p {
+  #wallpaperLabel > h2 {
     color: var(--cros-text-color-primary);
+    display: inline-block;
     font: var(--personalization-app-label-font);
     margin: 14px 0;
   }
 
+  iron-icon[icon='personalization:managed'] {
+    --iron-icon-fill-color: var(--cros-icon-color-secondary);
+  }
+
   #wallpaperButton {
     --cr-icon-button-size: 48px;
     /* Make the arrow align with the thumbnail image */
@@ -58,22 +63,47 @@
 </style>
 <div class="preview-container" id="container">
   <div id="wallpaperLabel">
-    <p on-click="onClickWallpaper_" class="clickable">$i18n{wallpaperLabel}</p>
+    <template is="dom-if" if="[[showPlaceholders_(imageLoading_, image_)]]">
+      <h2>$i18n{wallpaperLabel}</h2>
+    </template>
+    <template is="dom-if" if="[[!showPlaceholders_(imageLoading_, image_)]]">
+      <template is="dom-if" if="[[!isPolicyControlled_(image_)]]">
+        <h2 on-click="onClickWallpaper_" class="clickable">
+          $i18n{wallpaperLabel}
+        </h2>
     <cr-icon-button id="wallpaperButton" iron-icon="cr:chevron-right"
         role="button" on-click="onClickWallpaper_"
         class="tast-open-subpage"
         aria-label="$i18n{ariaLabelChangeWallpaper}">
     </cr-icon-button>
+      </template>
+      <template is="dom-if" if="[[isPolicyControlled_(image_)]]">
+        <p>$i18n{wallpaperLabel}</p>
+        <iron-icon icon="personalization:managed" title="$i18n{managedSetting}">
+        </iron-icon>
+      </template>
+    </template>
   </div>
-  <template is="dom-if" if="[[showPlaceholders_(isLoading_, showImage_)]]">
+  <template is="dom-if" if="[[showPlaceholders_(imageLoading_, image_)]]">
     <div id="imagePlaceholder" class="photo-images-container placeholder"></div>
   </template>
-  <template is="dom-if" if="[[showImage_]]">
+  <template is="dom-if" if="[[!showPlaceholders_(imageLoading_, image_)]]">
+    <template is="dom-if" if="[[!isPolicyControlled_(image_)]]">
       <div id="imageContainer" class="photo-images-container clickable"
           on-click="onClickWallpaper_" on-keypress="onClickWallpaper_">
-        <img src$="[[getImageSrc_(image_)]]" alt$="[[getImageAltDescription_(image_)]]">
+        <img src$="[[getImageSrc_(image_)]]"
+            alt$="[[getImageAltDescription_(image_)]]">
         <div id="shelf"></div>
       </div>
+    </template>
+    <template is="dom-if" if="[[isPolicyControlled_(image_)]]">
+      <div id="imageContainer" class="photo-images-container">
+        <img src$="[[getImageSrc_(image_)]]"
+            aria-description="$i18n{managedSetting}"
+            alt$="[[getImageAltDescription_(image_)]]">
+        <div id="shelf"></div>
+      </div>
+    </template>
   </template>
   <slot></slot>
 </div>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts
index 16d1ea3..716b8da 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts
@@ -14,6 +14,8 @@
 import './trusted_style.css.js';
 import '../cros_button_style.css.js';
 
+import {assert} from 'chrome://resources/js/assert_ts.js';
+
 import {getLocalStorageAttribution, isNonEmptyArray} from '../../common/utils.js';
 import {CurrentWallpaper, WallpaperProviderInterface, WallpaperType} from '../personalization_app.mojom-webui.js';
 import {Paths, PersonalizationRouter} from '../personalization_router_element.js';
@@ -36,20 +38,16 @@
     return {
       image_: {
         type: Object,
+        value: null,
       },
       imageLoading_: {
         type: Boolean,
       },
-      showImage_: {
-        type: Boolean,
-        computed: 'computeShowImage_(image_, imageLoading_)',
-      }
     };
   }
 
   private image_: CurrentWallpaper|null;
   private imageLoading_: boolean;
-  private showImage_: boolean;
   private wallpaperProvider_: WallpaperProviderInterface;
 
   constructor() {
@@ -71,7 +69,8 @@
   /**
    * Navigate to wallpaper collections page.
    */
-  onClickWallpaper_() {
+  private onClickWallpaper_() {
+    assert(!!this.image_ && this.image_.type !== WallpaperType.kPolicy);
     PersonalizationRouter.instance().goToRoute(Paths.COLLECTIONS);
   }
 
@@ -109,18 +108,17 @@
         this.i18n('unknownImageAttribution')}`;
   }
 
-  private computeShowImage_(image: CurrentWallpaper|null, loading: boolean):
-      boolean {
-    // Specifically check === false to avoid undefined case while component is
-    // initializing.
-    return loading === false && !!image;
+  /**
+   * Returns visible state of loading placeholder.
+   */
+  private showPlaceholders_(
+      imageLoading: boolean, image: CurrentWallpaper|null): boolean {
+    return imageLoading || !image;
   }
 
-  /**
-   * Returns hidden state of loading placeholder.
-   */
-  private showPlaceholders_(loading: boolean, showImage: boolean): boolean {
-    return loading || !showImage;
+  private isPolicyControlled_(image: CurrentWallpaper|null): boolean {
+    return !!image && image.type === WallpaperType.kPolicy;
   }
 }
+
 customElements.define(WallpaperPreview.is, WallpaperPreview);
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts
index 8f9d30d..c74a58d 100644
--- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts
+++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_subpage_element.ts
@@ -7,14 +7,15 @@
  * personalization SWA.
  */
 
-import {loadTimeData} from '//resources/js/load_time_data.m.js';
-import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
-import {Paths} from '../personalization_router_element.js';
+import {CurrentWallpaper, WallpaperType} from '../personalization_app.mojom-webui.js';
+import {Paths, PersonalizationRouter} from '../personalization_router_element.js';
+import {WithPersonalizationStore} from '../personalization_store.js';
 
 import {getTemplate} from './wallpaper_subpage_element.html.js';
 
-export class WallpaperSubpage extends PolymerElement {
+export class WallpaperSubpage extends WithPersonalizationStore {
   static get is() {
     return 'wallpaper-subpage';
   }
@@ -24,11 +25,33 @@
   }
 
   static get properties() {
-    return {path: String, queryParams: Object};
+    return {
+      path: String,
+      queryParams: Object,
+      currentSelected_: {
+        type: Object,
+        value: null,
+        observer: 'onCurrentSelectedChanged_',
+      },
+    };
   }
 
   path: string;
   queryParams: Record<string, string>;
+  currentSelected_: CurrentWallpaper|null;
+
+  override connectedCallback(): void {
+    super.connectedCallback();
+    this.watch('currentSelected_', state => state.wallpaper.currentSelected);
+    this.updateFromStore();
+  }
+
+  private onCurrentSelectedChanged_(value: CurrentWallpaper|null) {
+    if (value && value.type === WallpaperType.kPolicy &&
+        loadTimeData.getBoolean('isPersonalizationHubEnabled')) {
+      PersonalizationRouter.reloadAtRoot();
+    }
+  }
 
   private shouldShowCollections_(path: string): boolean {
     return path === Paths.COLLECTIONS;
diff --git a/ash/webui/shimless_rma/resources/shimless_rma.js b/ash/webui/shimless_rma/resources/shimless_rma.js
index 38a8ec4b..b84a5db 100644
--- a/ash/webui/shimless_rma/resources/shimless_rma.js
+++ b/ash/webui/shimless_rma/resources/shimless_rma.js
@@ -151,7 +151,7 @@
   [State.kUpdateRoFirmware]: {
     componentIs: 'reimaging-firmware-update-page',
     requiresReloadWhenShown: false,
-    buttonNext: ButtonState.HIDDEN,
+    buttonNext: ButtonState.DISABLED,
     buttonExit: ButtonState.HIDDEN,
     buttonBack: ButtonState.HIDDEN,
   },
diff --git a/ash/wm/base_state.cc b/ash/wm/base_state.cc
index acebe3c..a469df3 100644
--- a/ash/wm/base_state.cc
+++ b/ash/wm/base_state.cc
@@ -85,6 +85,8 @@
       return WindowStateType::kPinned;
     case WM_EVENT_PIP:
       return WindowStateType::kPip;
+    case WM_EVENT_FLOAT:
+      return WindowStateType::kFloated;
     case WM_EVENT_TRUSTED_PIN:
       return WindowStateType::kTrustedPinned;
     default:
diff --git a/ash/wm/default_state.cc b/ash/wm/default_state.cc
index 158ce96..875405c 100644
--- a/ash/wm/default_state.cc
+++ b/ash/wm/default_state.cc
@@ -11,6 +11,7 @@
 #include "ash/screen_util.h"
 #include "ash/shell.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/float/float_controller.h"
 #include "ash/wm/screen_pinning_controller.h"
 #include "ash/wm/splitview/split_view_controller.h"
 #include "ash/wm/splitview/split_view_metrics_controller.h"
@@ -21,6 +22,8 @@
 #include "ash/wm/wm_event.h"
 #include "ash/wm/workspace_controller.h"
 #include "base/bind.h"
+#include "base/check.h"
+#include "base/check_op.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "chromeos/ui/base/window_state_type.h"
@@ -434,6 +437,20 @@
   window_state->UpdateWindowPropertiesFromStateType();
   window_state->NotifyPreStateTypeChange(previous_state_type);
 
+  auto* const float_controller = Shell::Get()->float_controller();
+  auto* window = window_state->window();
+  if (state_type_ == WindowStateType::kFloated) {
+    DCHECK_EQ(next_state_type, WindowStateType::kFloated);
+    // Add window to float container.
+    float_controller->Float(window);
+  }
+
+  // Unfloat floated window when exiting float state to another state.
+  if (previous_state_type == WindowStateType::kFloated) {
+    // Remove float window from float container.
+    float_controller->Unfloat(window);
+  }
+
   // Don't update the window if the window is detached from parent.
   // This can happen during dragging.
   // TODO(oshima): This was added for DOCKED windows. Investigate if
@@ -573,6 +590,11 @@
       break;
     case WindowStateType::kInactive:
     case WindowStateType::kAutoPositioned:
+    case WindowStateType::kFloated:
+      // TODO(crbug.com/1331078): Handle Float Size and Position requirement.
+      // Temporarily set to current bounds.
+      bounds_in_parent = window->bounds();
+      break;
     case WindowStateType::kPip:
       return;
   }
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc
index 8b4300e4..b03e82d 100644
--- a/ash/wm/desks/desk_mini_view.cc
+++ b/ash/wm/desks/desk_mini_view.cc
@@ -53,8 +53,11 @@
 }
 
 // Tells whether `desk` contains an app window itself or if at least one visible
-// on all desks window exists.
+// on all desk window exists. Returns false if `desk` is nullptr.
 bool ContainsAppWindows(Desk* desk) {
+  if (!desk)
+    return false;
+
   return desk->ContainsAppWindows() ||
          !DesksController::Get()->visible_on_all_desks_windows().empty();
 }
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index aac8803..d8d2f6d 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -224,11 +224,14 @@
 
 void ShowDeskRemovalUndoToast(const std::string& toast_id,
                               base::RepeatingClosure dismiss_callback,
-                              base::RepeatingClosure expired_callback) {
+                              base::RepeatingClosure expired_callback,
+                              bool use_persistent_toast) {
+  // If ChromeVox is enabled, then we want the toast to be infinite duration.
   ToastData undo_toast_data(
       toast_id, ash::ToastCatalogName::kUndoCloseAll,
       l10n_util::GetStringUTF16(IDS_ASH_DESKS_CLOSE_ALL_TOAST_TEXT),
-      ToastData::kDefaultToastDuration,
+      use_persistent_toast ? ToastData::kInfiniteDuration
+                           : ToastData::kDefaultToastDuration,
       /*visible_on_lock_screen=*/false,
       /*has_dismiss_button=*/true,
       l10n_util::GetStringUTF16(IDS_ASH_DESKS_CLOSE_ALL_UNDO_TEXT));
@@ -239,8 +242,8 @@
 
 }  // namespace
 
-// Class that can hold the data for a removed desk while it waits for a user to
-// confirm its deletion.
+// Class that can hold the data for a removed desk while it waits for a user
+// to confirm its deletion.
 class DesksController::RemovedDeskData {
  public:
   RemovedDeskData(std::unique_ptr<Desk> desk, int index)
@@ -248,7 +251,11 @@
                                      ++g_close_desk_toast_counter)),
         was_active_(desk->is_active()),
         desk_(std::move(desk)),
-        index_(index) {
+        index_(index),
+        is_toast_persistent_(Shell::Get()
+                                 ->accessibility_controller()
+                                 ->spoken_feedback()
+                                 .enabled()) {
     desk_->set_is_desk_being_removed(true);
   }
 
@@ -266,6 +273,7 @@
   bool was_active() const { return was_active_; }
   Desk* desk() { return desk_.get(); }
   int index() const { return index_; }
+  bool is_toast_persistent() const { return is_toast_persistent_; }
   std::unique_ptr<Desk> AcquireDesk() { return std::move(desk_); }
 
  private:
@@ -273,6 +281,11 @@
   const bool was_active_;
   std::unique_ptr<Desk> desk_;
   const int index_;
+
+  // If this was created in overview with ChromeVox enabled and then ChromeVox
+  // is exited before this is destroyed, then we still need to know to destroy
+  // it when overview closes.
+  const bool is_toast_persistent_;
 };
 
 // Helper class which wraps around a OneShotTimer and used for recording how
@@ -1029,9 +1042,9 @@
 }
 
 void DesksController::CreateNewDeskForTemplate(
-    const std::u16string& template_name,
     bool activate_desk,
-    base::OnceCallback<void(const Desk*)> callback) {
+    base::OnceCallback<void(const Desk*)> callback,
+    const std::u16string& customized_desk_name) {
   DCHECK(!callback.is_null());
 
   if (!CanCreateDesks()) {
@@ -1044,18 +1057,27 @@
   if (animation_)
     animation_.reset();
 
-  // Change the desk name if the current name already exists.
-  int count = 1;
-  std::u16string desk_name = template_name;
-  while (HasDeskWithName(desk_name)) {
-    desk_name = std::u16string(template_name)
-                    .append(u" (" + base::FormatNumber(count) + u")");
-    count++;
+  // Desk name was set to a default name upon creation. If
+  // `customized_desk_name` is provided, override desk name to be
+  // `customized_desk_name` or `customized_desk_name ({counter})` to resolve
+  // naming conflicts.
+  std::u16string desk_name;
+  if (!customized_desk_name.empty()) {
+    int count = 1;
+    desk_name = customized_desk_name;
+    while (HasDeskWithName(desk_name)) {
+      desk_name = std::u16string(customized_desk_name)
+                      .append(u" (" + base::FormatNumber(count) + u")");
+      count++;
+    }
   }
 
   NewDesk(DesksCreationRemovalSource::kLaunchTemplate);
   Desk* desk = desks().back().get();
-  desk->SetName(desk_name, /*set_by_user=*/true);
+
+  if (!desk_name.empty()) {
+    desk->SetName(desk_name, /*set_by_user=*/true);
+  }
   // Force update user prefs because `SetName()` does not trigger it.
   desks_restore_util::UpdatePrimaryUserDeskNamesPrefs();
 
@@ -1207,6 +1229,8 @@
             case chromeos::WindowStateType::kPinned:
             case chromeos::WindowStateType::kTrustedPinned:
             case chromeos::WindowStateType::kPip:
+            // TODO(crbug.com/1331825): Float state support for desk template.
+            case chromeos::WindowStateType::kFloated:
               NOTREACHED();
               break;
           }
@@ -1259,6 +1283,35 @@
   ToastManager::Get()->Cancel(toast_id);
 }
 
+void DesksController::MaybeDismissPersistentDeskRemovalToast() {
+  if (temporary_removed_desk_ &&
+      temporary_removed_desk_->is_toast_persistent()) {
+    ToastManager::Get()->Cancel(temporary_removed_desk_->toast_id());
+  }
+}
+
+bool DesksController::MaybeToggleA11yHighlightOnUndoDeskRemovalToast() {
+  if (!temporary_removed_desk_ ||
+      !ToastManager::Get()->IsRunning(temporary_removed_desk_->toast_id())) {
+    return false;
+  }
+
+  return ToastManager::Get()
+      ->MaybeToggleA11yHighlightOnActiveToastDismissButton(
+          temporary_removed_desk_->toast_id());
+}
+
+bool DesksController::MaybeActivateDeskRemovalUndoButtonOnHighlightedToast() {
+  if (!temporary_removed_desk_ ||
+      !ToastManager::Get()->IsRunning(temporary_removed_desk_->toast_id())) {
+    return false;
+  }
+
+  return ToastManager::Get()
+      ->MaybeActivateHighlightedDismissButtonOnActiveToast(
+          temporary_removed_desk_->toast_id());
+}
+
 void DesksController::OnWindowActivating(ActivationReason reason,
                                          aura::Window* gaining_active,
                                          aura::Window* losing_active) {
@@ -1591,7 +1644,8 @@
         /*expired_callback=*/
         base::BindRepeating(&DesksController::MaybeCommitPendingDeskRemoval,
                             base::Unretained(this),
-                            temporary_removed_desk_->toast_id()));
+                            temporary_removed_desk_->toast_id()),
+        temporary_removed_desk_->is_toast_persistent());
   }
 }
 
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h
index 38ecb00d..c155f17 100644
--- a/ash/wm/desks/desks_controller.h
+++ b/ash/wm/desks/desks_controller.h
@@ -307,13 +307,15 @@
                                    DeskTemplateType template_type,
                                    aura::Window* root_window_to_show) const;
 
-  // Creates (and optionally activates) a new desk for a template with name
-  // `template_name` or `template_name ({counter})` to resolve naming
-  // conflicts. Runs `callback` with the newly created desk if creation was
-  // successful, nullptr otherwise.
-  void CreateNewDeskForTemplate(const std::u16string& template_name,
-                                bool activate_desk,
-                                base::OnceCallback<void(const Desk*)> callback);
+  // Creates (and optionally activates) a new desk. If `customized_desk_name`
+  // is provided, desk name will be `customized_desk_name` or
+  // `customized_desk_name ({counter})` to resolve naming conflicts. Runs
+  // `callback` with the newly created desk if creation was successful, nullptr
+  // otherwise.
+  void CreateNewDeskForTemplate(
+      bool activate_desk,
+      base::OnceCallback<void(const Desk*)> callback,
+      const std::u16string& customized_desk_name = std::u16string());
 
   // Called when an app with `app_id` is a single instance app which is about to
   // get launched from a saved template. Moves the existing app instance to the
@@ -334,6 +336,20 @@
   // there is a desk removal in progress.
   void MaybeCancelDeskRemoval();
 
+  // Cancels the desk removal toast if there is currently a
+  // `temporary_removed_desk_` and
+  // `temporary_removed_desk_->is_toast_persistent()` is true.
+  void MaybeDismissPersistentDeskRemovalToast();
+
+  // Adds focus highlight to an active toast to undo desk removal if one is
+  // active and the toast is not already highlighted. Otherwise, it removes the
+  // highlight from an active toast and returns false.
+  bool MaybeToggleA11yHighlightOnUndoDeskRemovalToast();
+
+  // Activates the undo button on a highlighted toast to undo desk removal if
+  // one is active. Returns true if the activation was successful.
+  bool MaybeActivateDeskRemovalUndoButtonOnHighlightedToast();
+
   // ::wm::ActivationChangeObserver:
   void OnWindowActivating(ActivationReason reason,
                           aura::Window* gaining_active,
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 3a726122..848bddf 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -7913,6 +7913,43 @@
   EXPECT_TRUE(window.window()->transform().IsIdentity());
 }
 
+// Tests that we can undo close-all solely via keyboard navigation (tabbing to
+// the undo toast and pressing enter).
+TEST_F(DesksCloseAllTest, CanUndoDeskClosureThroughKeyboardNavigation) {
+  NewDesk();
+  Shell::Get()->accessibility_controller()->spoken_feedback().SetEnabled(true);
+  EnterOverview();
+  ASSERT_TRUE(Shell::Get()->overview_controller()->InOverviewSession());
+
+  // Tab to the first mini view and perform close-all on it.
+  SendKey(ui::VKEY_TAB);
+  ASSERT_EQ(GetPrimaryRootDesksBarView()->mini_views()[0],
+            Shell::Get()
+                ->overview_controller()
+                ->overview_session()
+                ->highlight_controller()
+                ->highlighted_view());
+  SendKey(ui::VKEY_W, ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN);
+  ASSERT_EQ(1u, DesksController::Get()->desks().size());
+
+  // Tab to the undo toast.
+  SendKey(ui::VKEY_TAB);
+  SendKey(ui::VKEY_TAB);
+  SendKey(ui::VKEY_TAB);
+
+  // If the highlight controller returns a nullptr after tabbing, then the undo
+  // toast's button should be highlighted.
+  ASSERT_EQ(nullptr, Shell::Get()
+                         ->overview_controller()
+                         ->overview_session()
+                         ->highlight_controller()
+                         ->highlighted_view());
+
+  // Pressing enter should restore the desk.
+  SendKey(ui::VKEY_RETURN);
+  EXPECT_EQ(2u, DesksController::Get()->desks().size());
+}
+
 // TODO(afakhry): Add more tests:
 // - Always on top windows are not tracked by any desk.
 // - Reusing containers when desks are removed and created.
diff --git a/ash/wm/desks/templates/saved_desk_presenter.cc b/ash/wm/desks/templates/saved_desk_presenter.cc
index df1b5ea5..970f18bb 100644
--- a/ash/wm/desks/templates/saved_desk_presenter.cc
+++ b/ash/wm/desks/templates/saved_desk_presenter.cc
@@ -308,10 +308,11 @@
   const auto saved_desk_type = entry->type();
   const bool activate_desk = saved_desk_type == DeskTemplateType::kTemplate;
   DesksController::Get()->CreateNewDeskForTemplate(
-      saved_desk_name, activate_desk,
+      activate_desk,
       base::BindOnce(&SavedDeskPresenter::OnNewDeskCreatedForTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(entry),
-                     time_launch_started, delay, root_window));
+                     time_launch_started, delay, root_window),
+      saved_desk_name);
 
   if (on_update_ui_closure_for_testing)
     std::move(on_update_ui_closure_for_testing).Run();
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc
index d347eee..29cdf17a 100644
--- a/ash/wm/float/float_controller.cc
+++ b/ash/wm/float/float_controller.cc
@@ -31,7 +31,7 @@
   // Only one floating window is allowed, reset previously floated window.
   ResetFloatedWindow();
   DCHECK(!float_window_);
-  DCHECK(window->GetProperty(chromeos::kWindowFloatTypeKey));
+  DCHECK(window->GetProperty(chromeos::kWindowToggleFloatKey));
   float_window_ = window;
   float_window_observation_.Observe(float_window_);
   aura::Window* float_container =
@@ -41,8 +41,8 @@
 }
 
 void FloatController::Unfloat(aura::Window* window) {
-  DCHECK(!window->GetProperty(chromeos::kWindowFloatTypeKey));
-  // Re-parent window to active desk container.
+  DCHECK(!window->GetProperty(chromeos::kWindowToggleFloatKey));
+  //  Re-parent window to active desk container.
   desks_util::GetActiveDeskContainerForRoot(float_window_->GetRootWindow())
       ->AddChild(float_window_);
   float_window_observation_.Reset();
@@ -51,7 +51,7 @@
 
 void FloatController::ResetFloatedWindow() {
   if (float_window_)
-    float_window_->SetProperty(chromeos::kWindowFloatTypeKey, false);
+    float_window_->SetProperty(chromeos::kWindowToggleFloatKey, false);
 }
 
 }  // namespace ash
\ No newline at end of file
diff --git a/ash/wm/float/float_controller.h b/ash/wm/float/float_controller.h
index 3466cc11..c02c19b 100644
--- a/ash/wm/float/float_controller.h
+++ b/ash/wm/float/float_controller.h
@@ -32,8 +32,7 @@
   void OnWindowDestroying(aura::Window* window) override;
 
  private:
-  friend class WindowState;
-
+  friend class DefaultState;
   // Floats/Unfloats `window`.
   // Only one floating window is allowed, floating a new window will
   // unfloat the other floated window (if any).
diff --git a/ash/wm/lock_window_state.cc b/ash/wm/lock_window_state.cc
index 5481d947..17a4abd 100644
--- a/ash/wm/lock_window_state.cc
+++ b/ash/wm/lock_window_state.cc
@@ -43,9 +43,9 @@
       UpdateWindow(window_state, WindowStateType::kFullscreen);
       break;
     case WM_EVENT_PIP:
+    case WM_EVENT_FLOAT:
     case WM_EVENT_PIN:
     case WM_EVENT_TRUSTED_PIN:
-    case WM_EVENT_TOGGLE_FLOATING:
       NOTREACHED();
       break;
     case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
diff --git a/ash/wm/multitask_menu_nudge_controller.cc b/ash/wm/multitask_menu_nudge_controller.cc
index 5fd5ef5..f4456f09 100644
--- a/ash/wm/multitask_menu_nudge_controller.cc
+++ b/ash/wm/multitask_menu_nudge_controller.cc
@@ -149,7 +149,9 @@
   // restore button (depending on the window state).
   auto* frame_header = chromeos::FrameHeader::Get(
       views::Widget::GetWidgetForNativeWindow(window_));
-  DCHECK(frame_header);
+  // Frame might not be in tests.
+  if (!frame_header)
+    return;
   anchor_view_ = frame_header->caption_button_container()->size_button();
   DCHECK(anchor_view_);
 
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc
index 0527704..3543022 100644
--- a/ash/wm/overview/overview_controller.cc
+++ b/ash/wm/overview/overview_controller.cc
@@ -142,6 +142,11 @@
 
   ToggleOverview(type);
   RecordOverviewEndAction(action);
+
+  // If there is an undo toast active and the toast was created when ChromeVox
+  // was enabled, then we need to close the toast when overview closes.
+  DesksController::Get()->MaybeDismissPersistentDeskRemovalToast();
+
   return true;
 }
 
diff --git a/ash/wm/overview/overview_highlight_controller.cc b/ash/wm/overview/overview_highlight_controller.cc
index c6a9c7a..a328b7f 100644
--- a/ash/wm/overview/overview_highlight_controller.cc
+++ b/ash/wm/overview/overview_highlight_controller.cc
@@ -51,9 +51,11 @@
     return;
 
   int index = 0;
+  bool item_was_deleted = false;
   if (!highlighted_view_) {
     // Pick up where we left off if |deleted_index_| has a value.
     if (deleted_index_) {
+      item_was_deleted = true;
       index = *deleted_index_ >= count ? 0 : *deleted_index_;
       deleted_index_.reset();
     } else if (reverse) {
@@ -68,6 +70,19 @@
     index = (((reverse ? -1 : 1) + current_index) + count) % count;
   }
 
+  // If we are moving over either end of the list of traversible views and there
+  // is an active toast with an undo button for desk removal  that can be
+  // highlighted, then we unfocus any traversible views while the dismiss button
+  // is focused.
+  if (((index == 0 && !reverse) || (index == count - 1 && reverse)) &&
+      !item_was_deleted &&
+      DesksController::Get()
+          ->MaybeToggleA11yHighlightOnUndoDeskRemovalToast()) {
+    SetFocusHighlightVisibility(false);
+    highlighted_view_ = nullptr;
+    return;
+  }
+
   UpdateHighlight(traversable_views[index]);
 }
 
@@ -124,6 +139,11 @@
 }
 
 bool OverviewHighlightController::MaybeActivateHighlightedView() {
+  if (DesksController::Get()
+          ->MaybeActivateDeskRemovalUndoButtonOnHighlightedToast()) {
+    return true;
+  }
+
   if (!highlighted_view_)
     return false;
 
diff --git a/ash/wm/tablet_mode/tablet_mode_window_state.cc b/ash/wm/tablet_mode/tablet_mode_window_state.cc
index 882e40b8..63cfc64 100644
--- a/ash/wm/tablet_mode/tablet_mode_window_state.cc
+++ b/ash/wm/tablet_mode/tablet_mode_window_state.cc
@@ -280,7 +280,6 @@
         UpdateWindow(window_state, WindowStateType::kTrustedPinned,
                      true /* animated */);
       break;
-    case WM_EVENT_TOGGLE_FLOATING:
     case WM_EVENT_TOGGLE_MAXIMIZE_CAPTION:
     case WM_EVENT_TOGGLE_VERTICAL_MAXIMIZE:
     case WM_EVENT_TOGGLE_HORIZONTAL_MAXIMIZE:
@@ -308,6 +307,9 @@
       }
       break;
     }
+    // TODO(shidi): Float is currently disabled for tablet mode.
+    case WM_EVENT_FLOAT:
+      break;
     case WM_EVENT_SNAP_PRIMARY:
     case WM_EVENT_SNAP_SECONDARY:
       DoTabletSnap(window_state, event->type());
diff --git a/ash/wm/window_state.cc b/ash/wm/window_state.cc
index 769b5a3..9b53ee15 100644
--- a/ash/wm/window_state.cc
+++ b/ash/wm/window_state.cc
@@ -100,6 +100,10 @@
         {WindowStateType::kSecondarySnapped, 1},
         {WindowStateType::kMaximized, 2},
         {WindowStateType::kFullscreen, 3},
+        // TODO(crbug.com/1330999): Special handling is needed for
+        // Fullscreen/Float restore behavior in
+        // WindowState::UpdateWindowStateRestoreHistoryStack.
+        {WindowStateType::kFloated, 3},
         {WindowStateType::kPip, 4},
         {WindowStateType::kMinimized, 4},
     });
@@ -333,6 +337,10 @@
   return GetStateType() == WindowStateType::kPip;
 }
 
+bool WindowState::IsFloated() const {
+  return GetStateType() == WindowStateType::kFloated;
+}
+
 bool WindowState::IsNormalStateType() const {
   return IsNormalWindowStateType(GetStateType());
 }
@@ -1142,15 +1150,20 @@
     }
     return;
   }
-  if (key == chromeos::kWindowFloatTypeKey) {
+  // `kWindowToggleFloatKey` is only used to toggle float event, not an
+  // indicator of window's float state. this is created to allow access from
+  // both chromeos/ash and avoid recursive call to `kWindowStateTypeKey`.
+  // TODO(shidi): Create API to allow outside access and remove this property.
+  if (key == chromeos::kWindowToggleFloatKey) {
     DCHECK(chromeos::wm::features::IsFloatWindowEnabled());
-    auto* const float_controller = Shell::Get()->float_controller();
-    if (window->GetProperty(chromeos::kWindowFloatTypeKey)) {
-      float_controller->Float(window);
+    if (IsFloated()) {
+      // If window is already floated, unfloat and restore.
+      Restore();
     } else {
-      float_controller->Unfloat(window);
+      WMEvent event(WM_EVENT_FLOAT);
+      OnWMEvent(&event);
+      return;
     }
-    return;
   }
   if (key == chromeos::kWindowStateTypeKey) {
     if (!ignore_property_change_) {
diff --git a/ash/wm/window_state.h b/ash/wm/window_state.h
index 5257182..567d0e6 100644
--- a/ash/wm/window_state.h
+++ b/ash/wm/window_state.h
@@ -135,6 +135,7 @@
   bool IsPinned() const;
   bool IsTrustedPinned() const;
   bool IsPip() const;
+  bool IsFloated() const;
 
   // True if the window's state type is chromeos::WindowStateType::kMaximized,
   // chromeos::WindowStateType::kFullscreen or
diff --git a/ash/wm/wm_event.cc b/ash/wm/wm_event.cc
index ea6ec42..1fb408f7 100644
--- a/ash/wm/wm_event.cc
+++ b/ash/wm/wm_event.cc
@@ -69,7 +69,6 @@
     case WM_EVENT_NORMAL:
     case WM_EVENT_MAXIMIZE:
     case WM_EVENT_MINIMIZE:
-    case WM_EVENT_TOGGLE_FLOATING:
     case WM_EVENT_FULLSCREEN:
     case WM_EVENT_SNAP_PRIMARY:
     case WM_EVENT_SNAP_SECONDARY:
@@ -78,6 +77,7 @@
     case WM_EVENT_PIN:
     case WM_EVENT_TRUSTED_PIN:
     case WM_EVENT_PIP:
+    case WM_EVENT_FLOAT:
       return true;
     default:
       break;
diff --git a/ash/wm/wm_event.h b/ash/wm/wm_event.h
index bff0f00..7f77c4f5 100644
--- a/ash/wm/wm_event.h
+++ b/ash/wm/wm_event.h
@@ -47,9 +47,6 @@
   // Following events are compond events which may lead to different
   // states depending on the current state.
 
-  // A user requested to make a window floating.
-  WM_EVENT_TOGGLE_FLOATING,
-
   // A user requested to toggle maximized state by double clicking window
   // header.
   WM_EVENT_TOGGLE_MAXIMIZE_CAPTION,
@@ -117,6 +114,9 @@
   // TODO(oshima): Consider consolidating this into
   // WM_EVENT_WORKAREA_BOUNDS_CHANGED
   WM_EVENT_SYSTEM_UI_AREA_CHANGED,
+
+  // A user requested to float a window.
+  WM_EVENT_FLOAT,
 };
 
 class SetBoundsWMEvent;
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc
index e9bddce1..7afcb1c16 100644
--- a/ash/wm/workspace/workspace_window_resizer.cc
+++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -368,9 +368,9 @@
 #if DCHECK_IS_ON()
   // Other state types either create a different window resizer, or none at all.
   std::vector<WindowStateType> draggable_states = {
-      WindowStateType::kDefault, WindowStateType::kNormal,
+      WindowStateType::kDefault,        WindowStateType::kNormal,
       WindowStateType::kPrimarySnapped, WindowStateType::kSecondarySnapped,
-      WindowStateType::kMaximized};
+      WindowStateType::kMaximized,      WindowStateType::kFloated};
   DCHECK(base::Contains(draggable_states, state));
 #endif
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index f990dad..ff7c1c9f 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -78,7 +78,7 @@
 # Chromecast builds have full control over the platform and ensure that
 # the kernel and glibc versions used have patched the vulnerabilities,
 # so it is safe to use mutex priority inheritance on Chromecast platform.
-assert(!enable_mutex_priority_inheritance || is_chromecast,
+assert(!enable_mutex_priority_inheritance || is_castos || is_cast_android,
        "Do not enable PI mutexes without consulting the security team")
 
 assert(!is_nacl || is_nacl_saigo,
@@ -1494,8 +1494,7 @@
   # Needed for <atomic> if using newer C++ library than sysroot, except if
   # building inside the cros_sdk environment - use host_toolchain as a
   # more robust check for this.
-  if (!use_sysroot &&
-      (is_android || ((is_linux || is_chromeos) && !is_chromecast)) &&
+  if (!use_sysroot && (is_android || is_chromeos || (is_linux && !is_castos)) &&
       host_toolchain != "//build/toolchain/cros:host") {
     libs += [ "atomic" ]
   }
@@ -1583,7 +1582,7 @@
 
   # Allow more direct string conversions on platforms with native utf8
   # strings
-  if (is_apple || is_chromeos || is_chromecast || is_fuchsia) {
+  if (is_apple || is_chromeos || is_castos || is_cast_android || is_fuchsia) {
     defines += [ "SYSTEM_NATIVE_UTF8" ]
   }
 
@@ -2289,7 +2288,7 @@
 
     # TODO(b/167763382) Find an alternate solution for Chromecast devices, since
     # adding the icui18n and icuuc deps significantly increases the binary size.
-    if (!is_chromecast) {
+    if (!is_castos && !is_cast_android) {
       sources += [ "time/time_exploded_icu.cc" ]
 
       # The ICU dependency is only needed on systems with a 32-bit time_t.
@@ -3520,7 +3519,7 @@
 
   # Allow more direct string conversions on platforms with native utf8
   # strings
-  if (is_apple || is_chromeos || is_chromecast || is_fuchsia) {
+  if (is_apple || is_chromeos || is_castos || is_cast_android || is_fuchsia) {
     defines += [ "SYSTEM_NATIVE_UTF8" ]
   }
 
@@ -4282,9 +4281,9 @@
       "//third_party/android_support_test_runner:runner_java",
       "//third_party/androidx:androidx_annotation_annotation_java",
       "//third_party/androidx:androidx_core_core_java",
+      "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
       "//third_party/hamcrest:hamcrest_java",
       "//third_party/junit",
-      "//third_party/ub-uiautomator:ub_uiautomator_java",
     ]
 
     sources = [
diff --git a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
index a6feb12..814b786 100644
--- a/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -399,11 +399,11 @@
       MaybeAdjustSize(size), "");
 }
 
-#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_CHROMECAST)
+#if BUILDFLAG(IS_CAST_ANDROID)
 extern "C" {
 void __real_free(void*);
 }  // extern "C"
-#endif
+#endif  // BUILDFLAG(IS_CAST_ANDROID)
 
 void PartitionFree(const AllocatorDispatch*, void* object, void* context) {
   ScopedDisallowAllocations guard{};
@@ -419,11 +419,11 @@
   }
 #endif  // BUILDFLAG(IS_APPLE)
 
-  // On Chromecast, there is at least one case where a system malloc() pointer
-  // can be passed to PartitionAlloc's free(). If we don't own the pointer, pass
-  // it along. This should not have a runtime cost vs regular Android, since on
-  // Android we have a PA_CHECK() rather than the branch here.
-#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(IS_CHROMECAST)
+  // On Android Chromecast devices, there is at least one case where a system
+  // malloc() pointer can be passed to PartitionAlloc's free(). If we don't own
+  // the pointer, pass it along. This should not have a runtime cost vs regular
+  // Android, since on Android we have a PA_CHECK() rather than the branch here.
+#if BUILDFLAG(IS_CAST_ANDROID)
   if (UNLIKELY(!partition_alloc::IsManagedByPartitionAlloc(
                    reinterpret_cast<uintptr_t>(object)) &&
                object)) {
@@ -432,7 +432,7 @@
     // here.
     return __real_free(object);
   }
-#endif
+#endif  // BUILDFLAG(IS_CAST_ANDROID)
 
   partition_alloc::ThreadSafePartitionRoot::FreeNoHooks(object);
 }
diff --git a/base/allocator/partition_allocator/BUILD.gn b/base/allocator/partition_allocator/BUILD.gn
index 34ede98..0aa0c78 100644
--- a/base/allocator/partition_allocator/BUILD.gn
+++ b/base/allocator/partition_allocator/BUILD.gn
@@ -436,7 +436,10 @@
 buildflag_header("chromecast_buildflags") {
   header = "chromecast_buildflags.h"
 
-  flags = [ "PA_IS_CASTOS=$is_castos" ]
+  flags = [
+    "PA_IS_CAST_ANDROID=$is_cast_android",
+    "PA_IS_CASTOS=$is_castos",
+  ]
 }
 
 buildflag_header("chromeos_buildflags") {
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
index 46c9ad7..9d7ce56 100644
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/partition_alloc_unittest.cc
@@ -4519,8 +4519,7 @@
 
 #endif  // defined(PA_USE_MTE_CHECKED_PTR_WITH_64_BITS_POINTERS)
 
-#if BUILDFLAG(IS_ANDROID) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
-    BUILDFLAG(PA_IS_CASTOS)
+#if BUILDFLAG(PA_IS_CAST_ANDROID) && BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
 extern "C" {
 void* __real_malloc(size_t);
 }  // extern "C"
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
index e9624ca6..571b1c8 100644
--- a/base/allocator/partition_allocator/partition_root.h
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -1128,9 +1128,10 @@
   // forward allocations we don't own to the system malloc() implementation in
   // these rare cases, assuming that some remain.
   //
-  // On Chromecast, this is already checked in PartitionFree() in the shim.
+  // On Android Chromecast devices, this is already checked in PartitionFree()
+  // in the shim.
 #if BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC) && \
-    ((BUILDFLAG(IS_ANDROID) && !BUILDFLAG(PA_IS_CASTOS)))
+    (BUILDFLAG(IS_ANDROID) && !BUILDFLAG(PA_IS_CAST_ANDROID))
   PA_CHECK(IsManagedByPartitionAlloc(object_addr));
 #endif
 
diff --git a/base/fuchsia/filtered_service_directory.h b/base/fuchsia/filtered_service_directory.h
index 157ca7d..169959bd 100644
--- a/base/fuchsia/filtered_service_directory.h
+++ b/base/fuchsia/filtered_service_directory.h
@@ -15,14 +15,6 @@
 #include "base/base_export.h"
 #include "base/strings/string_piece.h"
 
-// TODO(crbug.com/1196525): Remove once Chromecast calls are checking results.
-#include "build/chromecast_buildflags.h"
-#if BUILDFLAG(IS_CHROMECAST)
-#define MAYBE_NODISCARD
-#else
-#define MAYBE_NODISCARD [[nodiscard]]
-#endif
-
 namespace base {
 
 // ServiceDirectory that uses the supplied sys::ServiceDirectory to satisfy
@@ -40,12 +32,12 @@
   ~FilteredServiceDirectory();
 
   // Adds the specified service to the list of allowed services.
-  MAYBE_NODISCARD zx_status_t AddService(base::StringPiece service_name);
+  [[nodiscard]] zx_status_t AddService(base::StringPiece service_name);
 
   // Connects a directory client. The directory can be passed to a sandboxed
   // process to be used for /svc namespace.
-  MAYBE_NODISCARD zx_status_t
-  ConnectClient(fidl::InterfaceRequest<::fuchsia::io::Directory> dir_request);
+  [[nodiscard]] zx_status_t ConnectClient(
+      fidl::InterfaceRequest<::fuchsia::io::Directory> dir_request);
 
   // Accessor for the OutgoingDirectory, used to add handlers for services
   // in addition to those provided from |directory| via AddService().
diff --git a/base/i18n/icu_util.cc b/base/i18n/icu_util.cc
index 83c641d..a671af1 100644
--- a/base/i18n/icu_util.cc
+++ b/base/i18n/icu_util.cc
@@ -53,9 +53,8 @@
 #include "third_party/icu/source/common/unicode/unistr.h"
 #endif
 
-#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) ||   \
-    ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
-     !BUILDFLAG(IS_CHROMECAST))
+#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_FUCHSIA) || \
+    BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
 #include "third_party/icu/source/i18n/unicode/timezone.h"
 #endif
 
@@ -326,8 +325,7 @@
       FuchsiaIntlProfileWatcher::GetPrimaryTimeZoneIdForIcuInitialization();
   icu::TimeZone::adoptDefault(
       icu::TimeZone::createTimeZone(icu::UnicodeString::fromUTF8(zone_id)));
-#elif (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && \
-    !BUILDFLAG(IS_CHROMECAST)
+#elif BUILDFLAG(IS_CHROMEOS) || (BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CASTOS))
   // To respond to the time zone change properly, the default time zone
   // cache in ICU has to be populated on starting up.
   // See TimeZoneMonitorLinux::NotifyClientsFromImpl().
diff --git a/base/json/json_parser.cc b/base/json/json_parser.cc
index 468ea2d..91824d9e 100644
--- a/base/json/json_parser.cc
+++ b/base/json/json_parser.cc
@@ -423,7 +423,7 @@
     return absl::nullopt;
   }
 
-  std::vector<Value::DictStorage::value_type> dict_storage;
+  std::vector<Value::DeprecatedDictStorage::value_type> dict_storage;
 
   Token token = GetNextToken();
   while (token != T_OBJECT_END) {
@@ -473,7 +473,7 @@
   // Reverse |dict_storage| to keep the last of elements with the same key in
   // the input.
   ranges::reverse(dict_storage);
-  return Value(Value::DictStorage(std::move(dict_storage)));
+  return Value(Value::DeprecatedDictStorage(std::move(dict_storage)));
 }
 
 absl::optional<Value> JSONParser::ConsumeList() {
diff --git a/base/process/process_metrics_win.cc b/base/process/process_metrics_win.cc
index 78090502..016f431 100644
--- a/base/process/process_metrics_win.cc
+++ b/base/process/process_metrics_win.cc
@@ -167,6 +167,9 @@
   // constant rate TSC.
   return GetCumulativeCPUUsage();
 #else   // !defined(ARCH_CPU_ARM64)
+  if (!time_internal::HasConstantRateTSC())
+    return GetCumulativeCPUUsage();
+
   ULONG64 process_cycle_time = 0;
   if (!QueryProcessCycleTime(process_.get(), &process_cycle_time)) {
     NOTREACHED();
diff --git a/base/task/sequenced_task_runner.h b/base/task/sequenced_task_runner.h
index f755bba..90452fc 100644
--- a/base/task/sequenced_task_runner.h
+++ b/base/task/sequenced_task_runner.h
@@ -33,6 +33,7 @@
 class DelayedTaskManager;
 }
 class DeadlineTimer;
+class MetronomeTimer;
 class TimeDelta;
 class TimeTicks;
 
@@ -48,6 +49,7 @@
   friend class base::internal::DelayTimerBase;
   friend class base::internal::DelayedTaskManager;
   friend class base::DeadlineTimer;
+  friend class base::MetronomeTimer;
   friend class blink::MetronomeSource;
   friend class blink::TimerBase;
   friend class blink::WebRtcMetronomeTaskQueue;
diff --git a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
index 3ad851a..97e47eb6 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java
@@ -9,7 +9,8 @@
 import android.os.Build;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.runners.model.Statement;
 
diff --git a/base/time/time_exploded_posix.cc b/base/time/time_exploded_posix.cc
index e769489..45327a8 100644
--- a/base/time/time_exploded_posix.cc
+++ b/base/time/time_exploded_posix.cc
@@ -130,10 +130,10 @@
   if (sizeof(SysTime) < 8) {
 // TODO(b/167763382) Find an alternate solution for Chromecast devices, since
 // adding the icui18n dep significantly increases the binary size.
-#if !BUILDFLAG(IS_CHROMECAST)
+#if !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
     ExplodeUsingIcu(millis_since_unix_epoch, is_local, exploded);
     return;
-#endif  // !BUILDFLAG(IS_CHROMECAST)
+#endif  // !BUILDFLAG(IS_CASTOS) && !BUILDFLAG(IS_CAST_ANDROID)
   }
 
   // Split the |millis_since_unix_epoch| into separate seconds and millisecond
diff --git a/base/timer/timer.cc b/base/timer/timer.cc
index 75274373..04d1183 100644
--- a/base/timer/timer.cc
+++ b/base/timer/timer.cc
@@ -402,4 +402,71 @@
   // No more member accesses here: |this| could be deleted at this point.
 }
 
+MetronomeTimer::MetronomeTimer() = default;
+MetronomeTimer::~MetronomeTimer() = default;
+
+MetronomeTimer::MetronomeTimer(const Location& posted_from,
+                               TimeDelta interval,
+                               RepeatingClosure user_task,
+                               TimeTicks phase)
+    : TimerBase(posted_from),
+      interval_(interval),
+      user_task_(user_task),
+      phase_(phase) {}
+
+void MetronomeTimer::Start(const Location& posted_from,
+                           TimeDelta interval,
+                           RepeatingClosure user_task,
+                           TimeTicks phase) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  user_task_ = std::move(user_task);
+  posted_from_ = posted_from;
+  interval_ = interval;
+  phase_ = phase;
+
+  Reset();
+}
+
+void MetronomeTimer::OnStop() {
+  user_task_.Reset();
+  // No more member accesses here: |this| could be deleted after freeing
+  // |user_task_|.
+}
+
+void MetronomeTimer::Reset() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(user_task_);
+  // We can't reuse the |scheduled_task_|, so abandon it and post a new one.
+  AbandonScheduledTask();
+  ScheduleNewTask();
+}
+
+void MetronomeTimer::ScheduleNewTask() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  is_running_ = true;
+
+  // The next wake up is scheduled at the next aligned time which is at least
+  // `interval_ / 2` after now. `interval_ / 2` is added to avoid playing
+  // "catch-up" if wake ups are late.
+  TimeTicks deadline =
+      (TimeTicks::Now() + interval_ / 2).SnappedToNextTick(phase_, interval_);
+
+  delayed_task_handle_ = GetTaskRunner()->PostCancelableDelayedTaskAt(
+      base::subtle::PostDelayedTaskPassKey(), posted_from_,
+      BindOnce(&MetronomeTimer::OnScheduledTaskInvoked, Unretained(this)),
+      deadline, subtle::DelayPolicy::kPrecise);
+}
+
+void MetronomeTimer::OnScheduledTaskInvoked() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(!delayed_task_handle_.IsValid());
+
+  // Make a local copy of the task to run in case the task destroy the timer
+  // instance.
+  RepeatingClosure task = user_task_;
+  ScheduleNewTask();
+  std::move(task).Run();
+  // No more member accesses here: |this| could be deleted at this point.
+}
+
 }  // namespace base
diff --git a/base/timer/timer.h b/base/timer/timer.h
index 9e52ef0..a20af99c 100644
--- a/base/timer/timer.h
+++ b/base/timer/timer.h
@@ -11,6 +11,15 @@
 // - DeadlineTimer: Once at the specified `TimeTicks` time.
 // - RepeatingTimer: Repeatedly, with a specified `TimeDelta` delay before the
 //    first invocation and between invocations.
+// - MetronomeTimer: Repeatedly, with a specified `TimeDelta` delay between the
+//    beginning of each invocations such that a constant phase is respected.
+// (Retaining)OneShotTimer and RepeatingTimer automatically apply some leeway to
+// the delay whereas DeadlineTimer and MetronomeTimer allow more control over
+// the requested time. As a result, the former are generally more
+// power-efficient.
+// Prefer using (Retaining)OneShotTimer and RepeatingTimer because they
+// automatically apply some leeway to the delay which enables power-efficient
+// scheduling.
 
 // Scheduled invocations can be cancelled with Stop() or by deleting the
 // Timer. The latter makes it easy to ensure that an object is not accessed by a
@@ -452,6 +461,63 @@
   OnceClosure user_task_;
 };
 
+//-----------------------------------------------------------------------------
+// Repeatedly invokes a callback, waiting for a precise delay between the
+// beginning of each invocation. See usage notes at the top of the file.
+class BASE_EXPORT MetronomeTimer : public internal::TimerBase {
+ public:
+  MetronomeTimer();
+  ~MetronomeTimer() override;
+
+  MetronomeTimer(const MetronomeTimer&) = delete;
+  MetronomeTimer& operator=(const MetronomeTimer&) = delete;
+
+  MetronomeTimer(const Location& posted_from,
+                 TimeDelta interval,
+                 RepeatingClosure user_task,
+                 TimeTicks phase = TimeTicks());
+
+  // Start the timer to repeatedly run |user_task| at the specified |interval|;
+  // If not specified, the phase is up to the scheduler, otherwise each
+  // invocation starts as close as possible to `phase + n * delay` for some
+  // integer n. If the timer is already running, it will be replaced to call the
+  // given |user_task|.
+  void Start(const Location& posted_from,
+             TimeDelta interval,
+             RepeatingClosure user_task,
+             TimeTicks phase = TimeTicks());
+
+  // Same as the previous overload, except that the user task is specified by
+  // `receiver` and `method`.
+  template <class Receiver>
+  void Start(const Location& posted_from,
+             TimeDelta interval,
+             Receiver* receiver,
+             void (Receiver::*method)(),
+             TimeTicks phase = TimeTicks()) {
+    Start(posted_from, interval, BindOnce(method, Unretained(receiver)), phase);
+  }
+
+  // Call this method to reset the timer delay. The user task must be set. If
+  // the timer is not running, this will start it by posting a task.
+  void Reset();
+
+ protected:
+  void OnStop() override;
+
+  // Schedules |OnScheduledTaskInvoked()| to run on the current sequence at
+  // the next tick.
+  void ScheduleNewTask();
+
+ private:
+  // Called when the scheduled task is invoked to run the |user_task|.
+  void OnScheduledTaskInvoked();
+
+  TimeDelta interval_;
+  RepeatingClosure user_task_;
+  TimeTicks phase_;
+};
+
 }  // namespace base
 
 #endif  // BASE_TIMER_TIMER_H_
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
index 248ad7a..bd85512 100644
--- a/base/timer/timer_unittest.cc
+++ b/base/timer/timer_unittest.cc
@@ -538,6 +538,107 @@
   testing::Mock::VerifyAndClearExpectations(&destructed);
 }
 
+TEST(TimerTest, MetronomeTimer) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  MetronomeTimer timer;
+  TimeTicks start = TimeTicks::Now();
+
+  // Ensure the run_loop.Run() below doesn't straddle over multiple ticks.
+  task_environment.AdvanceClock(
+      start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start);
+  start = TimeTicks::Now();
+
+  RunLoop run_loop;
+  timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure());
+  run_loop.Run();
+  EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
+}
+
+TEST(TimerTest, MetronomeTimerCustomPhase) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  RunLoop run_loop;
+  MetronomeTimer timer;
+  TimeTicks start = TimeTicks::Now();
+
+  timer.Start(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start);
+  run_loop.Run();
+  EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
+}
+
+TEST(TimerTest, MetronomeTimerReset) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  RunLoop run_loop;
+  TimeTicks start = TimeTicks::Now();
+  MetronomeTimer timer(FROM_HERE, Seconds(5), run_loop.QuitClosure(), start);
+
+  timer.Reset();
+  run_loop.Run();
+  EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
+}
+
+TEST(TimerTest, MetronomeTimerStartTwice) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  MetronomeTimer timer;
+  TimeTicks start = TimeTicks::Now();
+
+  {
+    RunLoop run_loop;
+    timer.Start(FROM_HERE, Seconds(4), run_loop.QuitClosure(), start);
+    run_loop.Run();
+  }
+  EXPECT_EQ(start + Seconds(4), TimeTicks::Now());
+
+  {
+    RunLoop run_loop;
+    timer.Start(FROM_HERE, Seconds(2), run_loop.QuitClosure(), start);
+    run_loop.Run();
+  }
+  EXPECT_EQ(start + Seconds(6), TimeTicks::Now());
+}
+
+TEST(TimerTest, MetronomeTimerMultiple) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  MetronomeTimer timer;
+  TimeTicks start = TimeTicks::Now();
+
+  // Ensure the subsequent FastForwardBy() don't straddle over multiple ticks.
+  task_environment.AdvanceClock(
+      start.SnappedToNextTick(TimeTicks(), Seconds(5)) - start);
+
+  MockRepeatingCallback<void()> callback;
+  timer.Start(FROM_HERE, Seconds(5), callback.Get());
+
+  // The first tick is skipped because it is too close. Ticks at 5s and 10s.
+  EXPECT_CALL(callback, Run()).Times(2);
+  task_environment.FastForwardBy(Seconds(10));
+
+  EXPECT_CALL(callback, Run()).Times(2);
+  // Ticks at 15s and 25s, while 20s is missed.
+  task_environment.AdvanceClock(Seconds(12));
+  task_environment.FastForwardBy(Seconds(3));
+}
+
+TEST(TimerTest, MetronomeTimerCancel) {
+  test::TaskEnvironment task_environment(
+      test::TaskEnvironment::TimeSource::MOCK_TIME);
+  RunLoop run_loop;
+  MetronomeTimer timer;
+  TimeTicks start = TimeTicks::Now();
+
+  MockRepeatingCallback<void()> callback;
+  timer.Start(FROM_HERE, Seconds(5), callback.Get());
+
+  EXPECT_CALL(callback, Run()).Times(0);
+  timer.Stop();
+  task_environment.FastForwardBy(Seconds(5));
+  EXPECT_EQ(start + Seconds(5), TimeTicks::Now());
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          TimerTestWithThreadType,
                          testing::ValuesIn(testing_main_threads));
diff --git a/base/values.cc b/base/values.cc
index 3282df3..a63668de 100644
--- a/base/values.cc
+++ b/base/values.cc
@@ -231,7 +231,8 @@
 
 Value::Value(List&& value) noexcept : data_(std::move(value)) {}
 
-Value::Value(const DictStorage& value) : data_(absl::in_place_type_t<Dict>()) {
+Value::Value(const DeprecatedDictStorage& value)
+    : data_(absl::in_place_type_t<Dict>()) {
   dict().reserve(value.size());
   for (const auto& it : value) {
     dict().try_emplace(dict().end(), it.first,
@@ -239,7 +240,8 @@
   }
 }
 
-Value::Value(DictStorage&& value) : data_(absl::in_place_type_t<Dict>()) {
+Value::Value(DeprecatedDictStorage&& value)
+    : data_(absl::in_place_type_t<Dict>()) {
   dict().reserve(value.size());
   for (auto& it : value) {
     dict().try_emplace(dict().end(), std::move(it.first),
@@ -1380,8 +1382,8 @@
   return const_dict_iterator_proxy(&dict());
 }
 
-Value::DictStorage Value::TakeDictDeprecated() && {
-  DictStorage storage;
+Value::DeprecatedDictStorage Value::TakeDictDeprecated() && {
+  DeprecatedDictStorage storage;
   storage.reserve(dict().size());
   for (auto& pair : dict()) {
     storage.try_emplace(storage.end(), std::move(pair.first),
diff --git a/base/values.h b/base/values.h
index 8db7e6a..1b42ee1 100644
--- a/base/values.h
+++ b/base/values.h
@@ -207,13 +207,13 @@
 
   using DeprecatedListStorage = std::vector<Value>;
   using DeprecatedDictStorage = flat_map<std::string, Value>;
-  // TODO(https://crbug.com/1291666): Make these private.
+  // TODO(https://crbug.com/1291666): Make this private.
   using ListStorage = DeprecatedListStorage;
-  using DictStorage = DeprecatedDictStorage;
 
   // Like `DictStorage`, but with std::unique_ptr in the mapped type. This is
-  // due to legacy reasons, and should be removed once no caller relies on
-  // stability of pointers anymore.
+  // due to legacy reasons, and should be replaced with a private version of
+  // DeprecatedDictStorage once no caller relies on stability of pointers
+  // anymore.
   using LegacyDictStorage = flat_map<std::string, std::unique_ptr<Value>>;
 
   using DeprecatedListView = CheckedContiguousRange<ListStorage>;
@@ -303,8 +303,8 @@
   explicit Value(List&& value) noexcept;
 
   // DEPRECATED: prefer `Value(Dict&&)`.
-  explicit Value(const DictStorage& value);
-  explicit Value(DictStorage&& value);
+  explicit Value(const DeprecatedDictStorage& value);
+  explicit Value(DeprecatedDictStorage&& value);
 
   // DEPRECATED: prefer `Value(List&&)`.
   explicit Value(span<const Value> value);
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
index b221d45..431bbf47 100644
--- a/base/values_unittest.cc
+++ b/base/values_unittest.cc
@@ -193,8 +193,29 @@
   EXPECT_EQ(Value::Type::DICTIONARY, value.type());
 }
 
-TEST(ValuesTest, ConstructDictFromStorage) {
-  Value::DictStorage storage;
+TEST(ValuesTest, ConstructDictFromValueDict) {
+  Value::Dict dict;
+  dict.Set("foo", "bar");
+  {
+    Value value(dict.Clone());
+    EXPECT_EQ(Value::Type::DICT, value.type());
+    EXPECT_TRUE(value.GetIfDict());
+    EXPECT_TRUE(value.GetDict().FindString("foo"));
+    EXPECT_EQ("bar", *value.GetDict().FindString("foo"));
+  }
+
+  dict.Set("foo", "baz");
+  {
+    Value value(std::move(dict));
+    EXPECT_EQ(Value::Type::DICT, value.type());
+    EXPECT_TRUE(value.GetIfDict());
+    EXPECT_TRUE(value.GetDict().FindString("foo"));
+    EXPECT_EQ("baz", *value.GetDict().FindString("foo"));
+  }
+}
+
+TEST(ValuesTest, ConstructDictFromDeprecatedDictStorage) {
+  Value::DeprecatedDictStorage storage;
   storage.emplace("foo", "bar");
   {
     Value value(storage);
@@ -328,9 +349,9 @@
 }
 
 TEST(ValuesTest, CopyDictionary) {
-  Value::DictStorage storage;
-  storage.emplace("Int", 123);
-  Value value(std::move(storage));
+  Value::Dict dict;
+  dict.Set("Int", 123);
+  Value value(std::move(dict));
 
   Value copied_value(value.Clone());
   EXPECT_EQ(value, copied_value);
@@ -430,7 +451,27 @@
 }
 
 TEST(ValuesTest, MoveConstructDictionary) {
-  Value::DictStorage storage;
+  Value::Dict dict;
+  dict.Set("Int", 123);
+
+  Value value(std::move(dict));
+  Value moved_value(std::move(value));
+  EXPECT_EQ(Value::Type::DICTIONARY, moved_value.type());
+  EXPECT_EQ(123, moved_value.FindKey("Int")->GetInt());
+}
+
+TEST(ValuesTest, MoveAssignDictionary) {
+  Value::Dict dict;
+  dict.Set("Int", 123);
+
+  Value blank;
+  blank = Value(std::move(dict));
+  EXPECT_EQ(Value::Type::DICTIONARY, blank.type());
+  EXPECT_EQ(123, blank.FindKey("Int")->GetInt());
+}
+
+TEST(ValuesTest, MoveConstructDeprecatedDictStorage) {
+  Value::DeprecatedDictStorage storage;
   storage.emplace("Int", 123);
 
   Value value(std::move(storage));
@@ -439,8 +480,8 @@
   EXPECT_EQ(123, moved_value.FindKey("Int")->GetInt());
 }
 
-TEST(ValuesTest, MoveAssignDictionary) {
-  Value::DictStorage storage;
+TEST(ValuesTest, MoveAssignDeprecatedDictStorage) {
+  Value::DeprecatedDictStorage storage;
   storage.emplace("Int", 123);
 
   Value blank;
@@ -449,9 +490,9 @@
   EXPECT_EQ(123, blank.FindKey("Int")->GetInt());
 }
 
-TEST(ValuesTest, TakeDict) {
+TEST(ValuesTest, TakeDictDeprecated) {
   // Prepare a dict with a value of each type.
-  Value::DictStorage storage;
+  Value::DeprecatedDictStorage storage;
   storage.emplace("null", Value::Type::NONE);
   storage.emplace("bool", Value::Type::BOOLEAN);
   storage.emplace("int", Value::Type::INTEGER);
@@ -730,397 +771,397 @@
 }
 
 TEST(ValuesTest, FindKey) {
-  Value::DictStorage storage;
-  storage.emplace("foo", "bar");
-  Value dict(std::move(storage));
-  EXPECT_NE(nullptr, dict.FindKey("foo"));
-  EXPECT_EQ(nullptr, dict.FindKey("baz"));
+  Value::Dict dict;
+  dict.Set("foo", "bar");
+  Value value(std::move(dict));
+  EXPECT_NE(nullptr, value.FindKey("foo"));
+  EXPECT_EQ(nullptr, value.FindKey("baz"));
 
   // Single not found key.
-  bool found = dict.FindKey("notfound");
+  bool found = value.FindKey("notfound");
   EXPECT_FALSE(found);
 }
 
 TEST(ValuesTest, FindKeyChangeValue) {
-  Value::DictStorage storage;
-  storage.emplace("foo", "bar");
-  Value dict(std::move(storage));
-  Value* found = dict.FindKey("foo");
+  Value::Dict dict;
+  dict.Set("foo", "bar");
+  Value value(std::move(dict));
+  Value* found = value.FindKey("foo");
   EXPECT_NE(nullptr, found);
   EXPECT_EQ("bar", found->GetString());
 
   *found = Value(123);
-  EXPECT_EQ(123, dict.FindKey("foo")->GetInt());
+  EXPECT_EQ(123, value.FindKey("foo")->GetInt());
 }
 
 TEST(ValuesTest, FindKeyConst) {
-  Value::DictStorage storage;
-  storage.emplace("foo", "bar");
-  const Value dict(std::move(storage));
-  EXPECT_NE(nullptr, dict.FindKey("foo"));
-  EXPECT_EQ(nullptr, dict.FindKey("baz"));
+  Value::Dict dict;
+  dict.Set("foo", "bar");
+  const Value value(std::move(dict));
+  EXPECT_NE(nullptr, value.FindKey("foo"));
+  EXPECT_EQ(nullptr, value.FindKey("baz"));
 }
 
 TEST(ValuesTest, FindKeyOfType) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  Value dict(std::move(storage));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY));
+  Value value(std::move(dict));
+  EXPECT_NE(nullptr, value.FindKeyOfType("null", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::NONE));
+  EXPECT_NE(nullptr, value.FindKeyOfType("bool", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BOOLEAN));
+  EXPECT_NE(nullptr, value.FindKeyOfType("int", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::INTEGER));
+  EXPECT_NE(nullptr, value.FindKeyOfType("double", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DOUBLE));
+  EXPECT_NE(nullptr, value.FindKeyOfType("string", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::STRING));
+  EXPECT_NE(nullptr, value.FindKeyOfType("blob", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BINARY));
+  EXPECT_NE(nullptr, value.FindKeyOfType("list", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::LIST));
+  EXPECT_NE(nullptr, value.FindKeyOfType("dict", Value::Type::DICTIONARY));
 }
 
 TEST(ValuesTest, FindKeyOfTypeConst) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY));
+  const Value value(std::move(dict));
+  EXPECT_NE(nullptr, value.FindKeyOfType("null", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("null", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::NONE));
+  EXPECT_NE(nullptr, value.FindKeyOfType("bool", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("bool", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BOOLEAN));
+  EXPECT_NE(nullptr, value.FindKeyOfType("int", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("int", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::INTEGER));
+  EXPECT_NE(nullptr, value.FindKeyOfType("double", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("double", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DOUBLE));
+  EXPECT_NE(nullptr, value.FindKeyOfType("string", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("string", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::STRING));
+  EXPECT_NE(nullptr, value.FindKeyOfType("blob", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("blob", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::BINARY));
+  EXPECT_NE(nullptr, value.FindKeyOfType("list", Value::Type::LIST));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("list", Value::Type::DICTIONARY));
 
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY));
-  EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST));
-  EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::NONE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BOOLEAN));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::INTEGER));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::DOUBLE));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::STRING));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::BINARY));
+  EXPECT_EQ(nullptr, value.FindKeyOfType("dict", Value::Type::LIST));
+  EXPECT_NE(nullptr, value.FindKeyOfType("dict", Value::Type::DICTIONARY));
 }
 
 TEST(ValuesTest, FindBoolKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("null"));
-  EXPECT_NE(absl::nullopt, dict.FindBoolKey("bool"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("int"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("double"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("string"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("blob"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("list"));
-  EXPECT_EQ(absl::nullopt, dict.FindBoolKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("null"));
+  EXPECT_NE(absl::nullopt, value.FindBoolKey("bool"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("int"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("double"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("string"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("blob"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("list"));
+  EXPECT_EQ(absl::nullopt, value.FindBoolKey("dict"));
 }
 
 TEST(ValuesTest, FindIntKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("null"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("bool"));
-  EXPECT_NE(absl::nullopt, dict.FindIntKey("int"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("double"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("string"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("blob"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("list"));
-  EXPECT_EQ(absl::nullopt, dict.FindIntKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("null"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("bool"));
+  EXPECT_NE(absl::nullopt, value.FindIntKey("int"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("double"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("string"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("blob"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("list"));
+  EXPECT_EQ(absl::nullopt, value.FindIntKey("dict"));
 }
 
 TEST(ValuesTest, FindDoubleKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("null"));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("bool"));
-  EXPECT_NE(absl::nullopt, dict.FindDoubleKey("int"));
-  EXPECT_NE(absl::nullopt, dict.FindDoubleKey("double"));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("string"));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("blob"));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("list"));
-  EXPECT_EQ(absl::nullopt, dict.FindDoubleKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("null"));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("bool"));
+  EXPECT_NE(absl::nullopt, value.FindDoubleKey("int"));
+  EXPECT_NE(absl::nullopt, value.FindDoubleKey("double"));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("string"));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("blob"));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("list"));
+  EXPECT_EQ(absl::nullopt, value.FindDoubleKey("dict"));
 }
 
 TEST(ValuesTest, FindStringKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(nullptr, dict.FindStringKey("null"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("bool"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("int"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("double"));
-  EXPECT_NE(nullptr, dict.FindStringKey("string"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("blob"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("list"));
-  EXPECT_EQ(nullptr, dict.FindStringKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(nullptr, value.FindStringKey("null"));
+  EXPECT_EQ(nullptr, value.FindStringKey("bool"));
+  EXPECT_EQ(nullptr, value.FindStringKey("int"));
+  EXPECT_EQ(nullptr, value.FindStringKey("double"));
+  EXPECT_NE(nullptr, value.FindStringKey("string"));
+  EXPECT_EQ(nullptr, value.FindStringKey("blob"));
+  EXPECT_EQ(nullptr, value.FindStringKey("list"));
+  EXPECT_EQ(nullptr, value.FindStringKey("dict"));
 }
 
 TEST(ValuesTest, MutableFindStringKey) {
-  Value::DictStorage storage;
-  storage.emplace("string", "foo");
-  Value dict(std::move(storage));
+  Value::Dict dict;
+  dict.Set("string", "foo");
+  Value value(std::move(dict));
 
-  *(dict.FindStringKey("string")) = "bar";
+  *(value.FindStringKey("string")) = "bar";
 
-  Value::DictStorage expected_storage;
-  expected_storage.emplace("string", "bar");
-  Value expected_dict(std::move(expected_storage));
+  Value::Dict expected_dict;
+  expected_dict.Set("string", "bar");
+  Value expected_value(std::move(expected_dict));
 
-  EXPECT_EQ(expected_dict, dict);
+  EXPECT_EQ(expected_value, value);
 }
 
 TEST(ValuesTest, FindDictKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(nullptr, dict.FindDictKey("null"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("bool"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("int"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("double"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("string"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("blob"));
-  EXPECT_EQ(nullptr, dict.FindDictKey("list"));
-  EXPECT_NE(nullptr, dict.FindDictKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(nullptr, value.FindDictKey("null"));
+  EXPECT_EQ(nullptr, value.FindDictKey("bool"));
+  EXPECT_EQ(nullptr, value.FindDictKey("int"));
+  EXPECT_EQ(nullptr, value.FindDictKey("double"));
+  EXPECT_EQ(nullptr, value.FindDictKey("string"));
+  EXPECT_EQ(nullptr, value.FindDictKey("blob"));
+  EXPECT_EQ(nullptr, value.FindDictKey("list"));
+  EXPECT_NE(nullptr, value.FindDictKey("dict"));
 }
 
 TEST(ValuesTest, FindListKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(nullptr, dict.FindListKey("null"));
-  EXPECT_EQ(nullptr, dict.FindListKey("bool"));
-  EXPECT_EQ(nullptr, dict.FindListKey("int"));
-  EXPECT_EQ(nullptr, dict.FindListKey("double"));
-  EXPECT_EQ(nullptr, dict.FindListKey("string"));
-  EXPECT_EQ(nullptr, dict.FindListKey("blob"));
-  EXPECT_NE(nullptr, dict.FindListKey("list"));
-  EXPECT_EQ(nullptr, dict.FindListKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(nullptr, value.FindListKey("null"));
+  EXPECT_EQ(nullptr, value.FindListKey("bool"));
+  EXPECT_EQ(nullptr, value.FindListKey("int"));
+  EXPECT_EQ(nullptr, value.FindListKey("double"));
+  EXPECT_EQ(nullptr, value.FindListKey("string"));
+  EXPECT_EQ(nullptr, value.FindListKey("blob"));
+  EXPECT_NE(nullptr, value.FindListKey("list"));
+  EXPECT_EQ(nullptr, value.FindListKey("dict"));
 }
 
 TEST(ValuesTest, FindBlobKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  const Value dict(std::move(storage));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("null"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("bool"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("int"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("double"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("string"));
-  EXPECT_NE(nullptr, dict.FindBlobKey("blob"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("list"));
-  EXPECT_EQ(nullptr, dict.FindBlobKey("dict"));
+  const Value value(std::move(dict));
+  EXPECT_EQ(nullptr, value.FindBlobKey("null"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("bool"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("int"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("double"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("string"));
+  EXPECT_NE(nullptr, value.FindBlobKey("blob"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("list"));
+  EXPECT_EQ(nullptr, value.FindBlobKey("dict"));
 }
 
 TEST(ValuesTest, SetKey) {
-  Value::DictStorage storage;
-  storage.emplace("null", Value::Type::NONE);
-  storage.emplace("bool", Value::Type::BOOLEAN);
-  storage.emplace("int", Value::Type::INTEGER);
-  storage.emplace("double", Value::Type::DOUBLE);
-  storage.emplace("string", Value::Type::STRING);
-  storage.emplace("blob", Value::Type::BINARY);
-  storage.emplace("list", Value::Type::LIST);
-  storage.emplace("dict", Value::Type::DICTIONARY);
+  Value::Dict dict;
+  dict.Set("null", Value());
+  dict.Set("bool", false);
+  dict.Set("int", 0);
+  dict.Set("double", 0.0);
+  dict.Set("string", std::string());
+  dict.Set("blob", Value(Value::BlobStorage()));
+  dict.Set("list", Value::List());
+  dict.Set("dict", Value::Dict());
 
-  Value dict(Value::Type::DICTIONARY);
-  dict.SetKey(StringPiece("null"), Value(Value::Type::NONE));
-  dict.SetKey(StringPiece("bool"), Value(Value::Type::BOOLEAN));
-  dict.SetKey(std::string("int"), Value(Value::Type::INTEGER));
-  dict.SetKey(std::string("double"), Value(Value::Type::DOUBLE));
-  dict.SetKey(std::string("string"), Value(Value::Type::STRING));
-  dict.SetKey("blob", Value(Value::Type::BINARY));
-  dict.SetKey("list", Value(Value::Type::LIST));
-  dict.SetKey("dict", Value(Value::Type::DICTIONARY));
+  Value value(Value::Type::DICTIONARY);
+  value.SetKey(StringPiece("null"), Value(Value::Type::NONE));
+  value.SetKey(StringPiece("bool"), Value(Value::Type::BOOLEAN));
+  value.SetKey(std::string("int"), Value(Value::Type::INTEGER));
+  value.SetKey(std::string("double"), Value(Value::Type::DOUBLE));
+  value.SetKey(std::string("string"), Value(Value::Type::STRING));
+  value.SetKey("blob", Value(Value::Type::BINARY));
+  value.SetKey("list", Value(Value::Type::LIST));
+  value.SetKey("dict", Value(Value::Type::DICTIONARY));
 
-  EXPECT_EQ(Value(std::move(storage)), dict);
+  EXPECT_EQ(Value(std::move(dict)), value);
 }
 
 TEST(ValuesTest, SetBoolKey) {
@@ -2462,9 +2503,10 @@
     EXPECT_EQ(perfetto::TracedValueToString(Value(list)), "[2,3]");
   }
   {
-    Value::DictStorage dict;
-    dict["key"] = Value("value");
-    EXPECT_EQ(perfetto::TracedValueToString(Value(dict)), "{key:value}");
+    Value::Dict dict;
+    dict.Set("key", "value");
+    EXPECT_EQ(perfetto::TracedValueToString(Value(std::move(dict))),
+              "{key:value}");
   }
 }
 #endif  // BUILDFLAG(ENABLE_BASE_TRACING)
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 8782816a..973bffa 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -564,6 +564,7 @@
     "//components/security_interstitials/content/android:java",
     "//components/security_state/content/android:java",
     "//components/security_state/core:security_state_enums_java",
+    "//components/segmentation_platform/content:content_java",
     "//components/segmentation_platform/public:public_java",
     "//components/send_tab_to_self:send_tab_to_self_java",
     "//components/signin/core/browser:signin_enums_java",
@@ -1682,6 +1683,7 @@
     "//third_party/androidx:androidx_collection_collection_java",
     "//third_party/androidx:androidx_preference_preference_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/androidx:androidx_viewpager2_viewpager2_java",
     "//third_party/androidx:androidx_viewpager_viewpager_java",
     "//third_party/blink/public:blink_headers_java",
@@ -1694,7 +1696,6 @@
     "//third_party/junit",
     "//third_party/metrics_proto:metrics_proto_java",
     "//third_party/mockito:mockito_java",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:clipboard_java_test_support",
     "//ui/android:ui_java",
     "//ui/android:ui_java_test_support",
@@ -1801,8 +1802,8 @@
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_browser_browser_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java",
   ]
 
@@ -3282,9 +3283,9 @@
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/hamcrest:hamcrest_library_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
   ]
 }
 
@@ -3932,6 +3933,8 @@
     "java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java",
     "java/src/org/chromium/chrome/browser/crash/MinidumpUploadServiceImpl.java",
     "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java",
+    "java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java",
+    "java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java",
     "java/src/org/chromium/chrome/browser/datareduction/DataSaverOSSetting.java",
     "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java",
     "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothScanningPromptAndroidDelegate.java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 8791057..920ff8b5 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -477,6 +477,7 @@
   "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/BaseCustomTabActivityModule.java",
   "java/src/org/chromium/chrome/browser/customtabs/features/CustomTabNavigationBarController.java",
   "java/src/org/chromium/chrome/browser/customtabs/features/ImmersiveModeController.java",
+  "java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java",
   "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabBrowserControlsVisibilityDelegate.java",
   "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java",
   "java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarAnimationDelegate.java",
@@ -981,6 +982,7 @@
   "java/src/org/chromium/chrome/browser/searchwidget/SearchBoxDataProvider.java",
   "java/src/org/chromium/chrome/browser/searchwidget/SearchType.java",
   "java/src/org/chromium/chrome/browser/searchwidget/SearchWidgetProvider.java",
+  "java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java",
   "java/src/org/chromium/chrome/browser/services/gcm/ChromeGcmListenerServiceImpl.java",
   "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundServiceImpl.java",
   "java/src/org/chromium/chrome/browser/services/gcm/GCMBackgroundTask.java",
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
index f93665a..c7386047 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTestUtils.java
@@ -27,7 +27,6 @@
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.util.Base64;
 import android.view.View;
 import android.view.ViewGroup;
@@ -37,6 +36,7 @@
 import androidx.test.espresso.ViewAction;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.uiautomator.UiDevice;
 
 import org.hamcrest.Matcher;
 import org.junit.Assert;
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
index cb5ccaca..426b51d 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -54,7 +54,6 @@
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -68,6 +67,7 @@
 import androidx.test.espresso.contrib.AccessibilityChecks;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
index 36a8688..adb9627 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -11,6 +11,7 @@
 import android.graphics.Rect;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnLayoutChangeListener;
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 import android.widget.ImageView;
@@ -84,6 +85,7 @@
 
     private boolean mIsInitialized;
     private ViewTreeObserver.OnGlobalLayoutListener mGlobalLayoutListener;
+    private OnLayoutChangeListener mListLayoutListener;
 
     /**
      * Construct a coordinator for UI that shows a list of tabs.
@@ -259,7 +261,11 @@
         }
 
         if (mMode == TabListMode.GRID && selectionDelegateProvider == null) {
-            mGlobalLayoutListener = this::updateThumbnailAndSpanCount;
+            mGlobalLayoutListener = this::updateThumbnailLocation;
+            if (TabUiFeatureUtilities.isTabletGridTabSwitcherEnabled(mContext)) {
+                mListLayoutListener = (view, left, top, right, bottom, oldLeft, oldTop, oldRight,
+                        oldBottom) -> updateGridCardLayout(right - left);
+            }
         }
     }
 
@@ -311,23 +317,19 @@
         return true;
     }
 
-    private void updateThumbnailAndSpanCount() {
-        updateThumbnailLocation();
-        if (mMode == TabListMode.GRID
-                && TabUiFeatureUtilities.isTabletGridTabSwitcherEnabled(mContext)) {
-            // Determine and set span count
-            final GridLayoutManager layoutManager =
-                    (GridLayoutManager) mRecyclerView.getLayoutManager();
-            mMediator.updateSpanCount(layoutManager,
-                    mContext.getResources().getConfiguration().orientation,
-                    mContext.getResources().getConfiguration().screenWidthDp);
-            // Determine grid card width and account for margins on left and right.
-            final int cardWidthPx = (layoutManager.getWidth() / layoutManager.getSpanCount());
-            final int cardHeightPx = TabUtils.deriveGridCardHeight(cardWidthPx, mContext);
-            for (int i = 0; i < mModel.size(); i++) {
-                mModel.get(i).model.set(TabProperties.GRID_CARD_WIDTH, cardWidthPx);
-                mModel.get(i).model.set(TabProperties.GRID_CARD_HEIGHT, cardHeightPx);
-            }
+    private void updateGridCardLayout(int viewWidth) {
+        // Determine and set span count
+        final GridLayoutManager layoutManager =
+                (GridLayoutManager) mRecyclerView.getLayoutManager();
+        mMediator.updateSpanCount(layoutManager,
+                mContext.getResources().getConfiguration().orientation,
+                mContext.getResources().getConfiguration().screenWidthDp);
+        // Determine grid card width and account for margins on left and right.
+        final int cardWidthPx = (viewWidth / layoutManager.getSpanCount());
+        final int cardHeightPx = TabUtils.deriveGridCardHeight(cardWidthPx, mContext);
+        for (int i = 0; i < mModel.size(); i++) {
+            mModel.get(i).model.set(TabProperties.GRID_CARD_WIDTH, cardWidthPx);
+            mModel.get(i).model.set(TabProperties.GRID_CARD_HEIGHT, cardHeightPx);
         }
     }
 
@@ -394,6 +396,9 @@
         if (mGlobalLayoutListener != null) {
             mRecyclerView.getViewTreeObserver().addOnGlobalLayoutListener(mGlobalLayoutListener);
         }
+        if (mListLayoutListener != null) {
+            mRecyclerView.addOnLayoutChangeListener(mListLayoutListener);
+        }
         mRecyclerView.prepareTabSwitcherView();
         mMediator.prepareTabSwitcherView();
     }
@@ -402,6 +407,9 @@
         if (mGlobalLayoutListener != null) {
             mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
         }
+        if (mListLayoutListener != null) {
+            mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener);
+        }
         mRecyclerView.postHiding();
         mMediator.postHiding();
     }
@@ -415,6 +423,9 @@
         if (mGlobalLayoutListener != null) {
             mRecyclerView.getViewTreeObserver().removeOnGlobalLayoutListener(mGlobalLayoutListener);
         }
+        if (mListLayoutListener != null) {
+            mRecyclerView.removeOnLayoutChangeListener(mListLayoutListener);
+        }
         mRecyclerView.setRecyclerListener(null);
     }
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java
index 6b0bca6a..f7deb3f2 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java
@@ -28,7 +28,6 @@
 import android.os.Build;
 import android.provider.Settings;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.TextView;
@@ -36,6 +35,7 @@
 import androidx.test.espresso.NoMatchingRootException;
 import androidx.test.espresso.intent.Intents;
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
index 4d60f61..796b2d3 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
@@ -33,7 +33,6 @@
 import android.content.res.Configuration;
 import android.graphics.drawable.Animatable;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -42,6 +41,7 @@
 import androidx.test.espresso.NoMatchingRootException;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS
index e746f0c2..ac2385a 100644
--- a/chrome/android/java/DEPS
+++ b/chrome/android/java/DEPS
@@ -56,6 +56,7 @@
   "+components/permissions/android/java/src/org/chromium/components/permissions",
   "+components/search_engines/android/java/src/org/chromium/components/search_engines",
   "+components/security_state/content/android/java",
+  "+components/segmentation_platform/content/android/java",
   "+components/segmentation_platform/public/android/java",
   "+components/sync/android/java/src/org/chromium/components/sync",
   "+components/query_tiles/android/java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index cda122dc..a2c28b9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -433,6 +433,11 @@
                 mActivity.getApplicationContext().getPackageName(), targetActivityClassName);
         newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS);
+
+        if ((mIntent.getFlags() & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
+            newIntent.setFlags(newIntent.getFlags() | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+        }
+
         Uri uri = newIntent.getData();
         boolean isContentScheme = false;
         if (uri != null && UrlConstants.CONTENT_SCHEME.equals(uri.getScheme())) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 5b98383..b81362d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -90,8 +90,8 @@
     protected BaseCustomTabActivityComponent createComponent(
             ChromeActivityCommonsModule commonsModule) {
         BaseCustomTabActivityComponent component = super.createComponent(commonsModule);
-        mOpenTimeRecorder = new CustomTabsOpenTimeRecorder(
-                getLifecycleDispatcher(), mNavigationController, this::isFinishing);
+        mOpenTimeRecorder = new CustomTabsOpenTimeRecorder(getLifecycleDispatcher(),
+                mNavigationController, this::isFinishing, mIntentDataProvider);
         return component;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
index 8a58f6a5..ab17b3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java
@@ -19,7 +19,9 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
+import org.chromium.chrome.browser.customtabs.features.TabInteractionRecorder;
 import org.chromium.chrome.browser.dependency_injection.ActivityScope;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabHidingType;
@@ -191,6 +193,23 @@
         if (isFirstMainFrameCommit) mFirstCommitTimestamp = SystemClock.elapsedRealtime();
     }
 
+    @Override
+    public void onClosingStateChanged(Tab tab, boolean closing) {
+        if (!closing) return;
+
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_RETAINING_STATE)) {
+            TabInteractionRecorder observer = TabInteractionRecorder.getFromTab(tab);
+            if (observer != null) observer.onTabClosing();
+        }
+    }
+
+    @Override
+    public void onShown(Tab tab, int type) {
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_RETAINING_STATE)) {
+            TabInteractionRecorder.createForTab(tab);
+        }
+    }
+
     public void onFirstMeaningfulPaint(Tab tab) {
         mNavigationInfoCaptureTrigger.onFirstMeaningfulPaint(tab);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java
index d7a0a458..6bb9a92e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java
@@ -5,11 +5,14 @@
 package org.chromium.chrome.browser.customtabs;
 
 import android.os.SystemClock;
+import android.text.format.DateUtils;
 
 import androidx.annotation.IntDef;
 
+import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.BooleanSupplier;
+import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController;
 import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
@@ -35,6 +38,7 @@
 class CustomTabsOpenTimeRecorder implements StartStopWithNativeObserver {
     private final CustomTabActivityNavigationController mNavigationController;
     private final BooleanSupplier mIsCctFinishing;
+    private final BrowserServicesIntentDataProvider mIntent;
 
     private long mOnStartTimestampMs;
 
@@ -53,10 +57,11 @@
 
     public CustomTabsOpenTimeRecorder(ActivityLifecycleDispatcher lifecycleDispatcher,
             CustomTabActivityNavigationController navigationController,
-            BooleanSupplier isCctFinishing) {
+            BooleanSupplier isCctFinishing, BrowserServicesIntentDataProvider intent) {
         lifecycleDispatcher.register(this);
         mNavigationController = navigationController;
         mIsCctFinishing = isCctFinishing;
+        mIntent = intent;
     }
 
     @Override
@@ -71,13 +76,30 @@
         RecordHistogram.recordEnumeratedHistogram(
                 "CustomTabs.CloseCause", mCloseCause, CloseCause.COUNT);
 
+        long duration = SystemClock.elapsedRealtime() - mOnStartTimestampMs;
         // Additional check with |mIsCctFinishing| can eliminate some false positives.
         // See Javadoc for more details.
         if (mCloseCause == CloseCause.AUTOCLOSE && mIsCctFinishing.getAsBoolean()) {
-            long duration = SystemClock.elapsedRealtime() - mOnStartTimestampMs;
             RecordHistogram.recordLongTimesHistogram(
                     "CustomTabs.AutoclosedSessionDuration", duration);
         }
+
+        if (mIsCctFinishing.getAsBoolean()) {
+            long time = System.currentTimeMillis() / DateUtils.SECOND_IN_MILLIS;
+            String packageName = mIntent.getClientPackageName();
+            // TODO(crbug.com/1334500): add tracking didUserInteract.
+            boolean wasUserClose = mCloseCause != CloseCause.AUTOCLOSE;
+            boolean isPartial = mIntent.isPartialHeightCustomTab();
+
+            long recordDuration = Math.min(duration / DateUtils.SECOND_IN_MILLIS, 300);
+            // For the real implementation, there'll be a native method on this class or a new
+            // class entirely. Just for the proof-of-concept I tacked the native method onto another
+            // class that already have natives.
+            CustomTabsOpenTimeRecorderJni.get().recordCustomTabSession(time,
+                    (packageName != null ? packageName : ""), recordDuration, wasUserClose,
+                    isPartial);
+        }
+
         mOnStartTimestampMs = 0;
     }
 
@@ -90,4 +112,10 @@
     void onUserLeaveHint() {
         mCloseCause = CloseCause.USER_ACTION_ANDROID;
     }
+
+    @NativeMethods
+    interface Natives {
+        void recordCustomTabSession(long time, String packageName, long sessionDuration,
+                boolean wasAutomaticallyClosed, boolean isPartialCct);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
index 7b0a1d8..d274372 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/PartialCustomTabHeightStrategy.java
@@ -717,6 +717,12 @@
         return getFullyExpandedYCoordinate() + mFullyExpandedAdjustmentHeight;
     }
 
+    @Override
+    public boolean changeBackgroundColorForResizing() {
+        // Need to return true to keep the transparent background we set in the init step.
+        return true;
+    }
+
     @VisibleForTesting
     void setMockViewForTesting(LinearLayout navbar, ImageView spinnerView,
             CircularProgressDrawable spinner, View toolbar, View toolbarCoordinator,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java
new file mode 100644
index 0000000..7f36027
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java
@@ -0,0 +1,94 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs.features;
+
+import android.os.SystemClock;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.base.Log;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.tab.Tab;
+
+import java.util.Locale;
+
+/**
+ * Class used to monitor interactions for the current custom tab. This class is created in native
+ * and owned by C++ object. This class has the ability to record whether the current web content has
+ * seen interaction when the tab is closing, as well as the timestamp when this happens.
+ *
+ * Note that this object's lifecycle is bounded to a {@link WebContents} but not a {@link Tab}. To
+ * observe the first frame of tab load, this recorder has to attach to the web content before the
+ * first navigation for the visible frame finishes, or a pre-rendered frame become active.
+ * */
+@JNINamespace("customtabs")
+public class TabInteractionRecorder {
+    private static final String TAG = "CctInteraction";
+
+    private final long mNativeTabInteractionRecorder;
+
+    // Do not instantiate in Java.
+    private TabInteractionRecorder(long nativePtr) {
+        mNativeTabInteractionRecorder = nativePtr;
+    }
+
+    @CalledByNative
+    private static @Nullable TabInteractionRecorder create(long nativePtr) {
+        if (nativePtr == 0) return null;
+        return new TabInteractionRecorder(nativePtr);
+    }
+
+    /**
+     * Get the TabInteractionRecorder that lives in the main web contents of the given tab.
+     * Note that the object might be come stale if the web contents of the given tab is swapped
+     * after this function is called.
+     * */
+    public static @Nullable TabInteractionRecorder getFromTab(Tab tab) {
+        return TabInteractionRecorderJni.get().getFromTab(tab);
+    }
+
+    /**
+     * Create a TabInteractionRecorder and start observing the web contents in the given tab. If an
+     * observer already exists for the tab, do nothing.
+     */
+    public static void createForTab(Tab tab) {
+        TabInteractionRecorderJni.get().createForTab(tab);
+    }
+
+    /**
+     * Notify this recorder tab is being closed. Record whether this instance has seen any
+     * interaction, and the timestamp when the tab is closed, into SharedPreferences.
+     *
+     * This class works correctly assuming there will be only one tab opened throughout the lifetime
+     * of a given CCT session. If CCT ever changed into serving multiple tabs, this recorder will
+     * only works for the last tab being closed.
+     */
+    public void onTabClosing() {
+        long timestamp = SystemClock.uptimeMillis();
+        boolean hadInteraction =
+                TabInteractionRecorderJni.get().hadInteraction(mNativeTabInteractionRecorder);
+
+        Log.d(TAG,
+                String.format(Locale.US,
+                        "timestamp=%d, TabInteractionRecorder.recordInteractions=%b", timestamp,
+                        hadInteraction));
+
+        SharedPreferencesManager pref = SharedPreferencesManager.getInstance();
+        pref.writeLong(ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP, timestamp);
+        pref.writeBoolean(
+                ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION, hadInteraction);
+    }
+
+    @NativeMethods
+    interface Natives {
+        TabInteractionRecorder getFromTab(Tab tab);
+        TabInteractionRecorder createForTab(Tab tab);
+        boolean hadInteraction(long nativeTabInteractionRecorderAndroid);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
index c3404fde..5eb9a4f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java
@@ -244,7 +244,7 @@
 
     /**
      * Creates and returns an {@link Intent} that instantiates a new Chrome instance.
-     * @param activity The activity firing the intent.
+     * @param context The application context of the activity firing the intent.
      * @param instanceId ID of the new Chrome instance to be created.
      * @param preferNew {@code true} if the new instance should be instanted as a fresh
      *        new one not loading any tabs from a persistent disk file.
@@ -253,9 +253,9 @@
      * @return The created intent.
      */
     public static Intent createNewWindowIntent(
-            Activity activity, int instanceId, boolean preferNew, boolean openAdjacently) {
+            Context context, int instanceId, boolean preferNew, boolean openAdjacently) {
         assert instanceSwitcherEnabled();
-        Intent intent = new Intent(activity, ChromeTabbedActivity.class);
+        Intent intent = new Intent(context, ChromeTabbedActivity.class);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
         intent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
         if (instanceId != INVALID_INSTANCE_ID) {
@@ -263,7 +263,7 @@
         }
         if (preferNew) intent.putExtra(IntentHandler.EXTRA_PREFER_NEW, true);
         if (openAdjacently) intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT);
-        intent.putExtra(Browser.EXTRA_APPLICATION_ID, activity.getPackageName());
+        intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
         intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
         IntentUtils.addTrustedIntentExtras(intent);
         return intent;
@@ -587,6 +587,11 @@
                 String.valueOf(index));
     }
 
+    /**
+     * Read the time when an instance was last accessed.
+     * @param index Instance ID
+     * @return The time when the instance was last accessed.
+     */
     static long readLastAccessedTime(int index) {
         return SharedPreferencesManager.getInstance().readLong(lastAccessedTimeKey(index));
     }
@@ -754,4 +759,23 @@
                 isInMultiWindowMode(activity) ? MultiWindowState.MULTI_WINDOW
                                               : MultiWindowState.SINGLE_WINDOW);
     }
+
+    /**
+     * @return The instance ID of the Chrome window that was accessed last if the maximum number of
+     *         instances is open. If fewer than the maximum number is open, the default ID will be
+     *         returned, indicative of an unused window ID that can be potentially allocated to
+     *         launch a VIEW intent.
+     */
+    public static int getInstanceIdForViewIntent() {
+        int windowId = MultiWindowUtils.INVALID_INSTANCE_ID;
+        int maxInstances = MultiWindowUtils.getMaxInstances();
+        if (MultiWindowUtils.getInstanceCount() < maxInstances) return windowId;
+        for (int i = 0; i < maxInstances; i++) {
+            if (MultiWindowUtils.readLastAccessedTime(i)
+                    > MultiWindowUtils.readLastAccessedTime(windowId)) {
+                windowId = i;
+            }
+        }
+        return windowId;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
new file mode 100644
index 0000000..b9dd3c6
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/segmentation_platform/ContextualPageActionController.java
@@ -0,0 +1,78 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.segmentation_platform;
+
+import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tab.TabUtils;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarButtonController;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarStatePredictor;
+import org.chromium.components.segmentation_platform.OnDemandSegmentSelectionResult;
+import org.chromium.components.segmentation_platform.PageLoadTriggerContext;
+import org.chromium.components.segmentation_platform.SegmentationPlatformService;
+import org.chromium.content_public.browser.WebContents;
+
+/**
+ * Central class for contextual page actions bridging between UI and backend. Registers itself with
+ * segmentation platform for on-demand model execution on page load triggers. Provides updated
+ * button data to the toolbar when asked for it.
+ */
+public class ContextualPageActionController {
+    private static final String CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY = "contextual_page_action";
+
+    private SegmentationPlatformService mSegmentationPlatformService;
+    private final ObservableSupplier<Tab> mTabSupplier;
+    private final AdaptiveToolbarButtonController mAdaptiveToolbarButtonController;
+    private int mSegmentSelectionCallbackId;
+
+    /**
+     * Constructor.
+     * @param profileSupplier The supplier for current profile.
+     * @param tabSupplier The supplier of the current tab.
+     * @param adaptiveToolbarButtonController The {@link AdaptiveToolbarButtonController} that
+     *         handles the logic to decide between multiple buttons to show.
+     */
+    public ContextualPageActionController(ObservableSupplier<Profile> profileSupplier,
+            ObservableSupplier<Tab> tabSupplier,
+            AdaptiveToolbarButtonController adaptiveToolbarButtonController) {
+        mTabSupplier = tabSupplier;
+        mAdaptiveToolbarButtonController = adaptiveToolbarButtonController;
+        profileSupplier.addObserver(profile -> {
+            if (profile.isOffTheRecord()) return;
+            if (!AdaptiveToolbarFeatures.isContextualPageActionUiEnabled()) return;
+
+            mSegmentationPlatformService =
+                    SegmentationPlatformServiceFactory.getForProfile(profile);
+            mSegmentSelectionCallbackId =
+                    mSegmentationPlatformService.registerOnDemandSegmentSelectionCallback(
+                            CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY,
+                            this::onSegmentSelectionResult);
+        });
+    }
+
+    /** Called on destroy. */
+    public void destroy() {
+        if (mSegmentationPlatformService == null) return;
+        mSegmentationPlatformService.unregisterOnDemandSegmentSelectionCallback(
+                CONTEXTUAL_PAGE_ACTION_SEGMENTATION_KEY, mSegmentSelectionCallbackId);
+    }
+
+    private void onSegmentSelectionResult(OnDemandSegmentSelectionResult result) {
+        if (result == null || !(result.triggerContext instanceof PageLoadTriggerContext)) return;
+        WebContents webContents = ((PageLoadTriggerContext) result.triggerContext).webContents;
+        Tab processedTab = webContents == null || webContents.isDestroyed()
+                ? null
+                : TabUtils.fromWebContents(webContents);
+        Tab currentTab = mTabSupplier.get();
+        boolean isSameTab = currentTab != null && processedTab != null
+                && currentTab.getId() == processedTab.getId();
+        if (!isSameTab) return;
+        mAdaptiveToolbarButtonController.showDynamicAction(
+                AdaptiveToolbarStatePredictor.getAdaptiveToolbarButtonVariantFromSegmentId(
+                        result.segmentSelectionResult.selectedSegment));
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
index aa5139c..94c8cc9e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -22,6 +22,7 @@
   "+chrome/browser/usb/android/java/src/org/chromium/chrome/browser/usb/UsbNotificationManager.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/media/MediaCaptureNotificationServiceImpl.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/metrics/UkmRecorder.java",
+  "+chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtils.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageBridge.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageOrigin.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
index f0441e6..9934fc8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegate.java
@@ -5,6 +5,8 @@
 package org.chromium.chrome.browser.tab;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
 import android.os.Build;
 import android.os.Build.VERSION;
 import android.view.DragAndDropPermissions;
@@ -17,6 +19,8 @@
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.content_public.browser.RenderWidgetHostView;
@@ -57,7 +61,7 @@
 
             boolean supportDropInChrome = ContentFeatureList.getFieldTrialParamByFeatureAsBoolean(
                     ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, PARAM_DROP_IN_CHROME, false);
-            if (VERSION.SDK_INT >= Build.VERSION_CODES.N && supportDropInChrome) {
+            if (VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                 DragAndDropBrowserDelegate browserDelegate =
                         new DragAndDropBrowserDelegateImpl(mTab, supportDropInChrome);
                 getDragAndDropDelegate().setDragAndDropBrowserDelegate(browserDelegate);
@@ -194,5 +198,17 @@
             }
             return activity.requestDragAndDropPermissions(dropEvent);
         }
+
+        @Override
+        public Intent createLinkIntent(String urlString) {
+            Intent intent = null;
+            if (ChromeFeatureList.isEnabled(ChromeFeatureList.NEW_INSTANCE_FROM_DRAGGED_LINK)) {
+                intent = MultiWindowUtils.createNewWindowIntent(
+                        mTab.getContext().getApplicationContext(),
+                        MultiWindowUtils.getInstanceIdForViewIntent(), true, false);
+                intent.setData(Uri.parse(urlString));
+            }
+            return intent;
+        }
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index 61f49f8..9280b87d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -94,6 +94,7 @@
 import org.chromium.chrome.browser.price_tracking.PriceTrackingButtonController;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
+import org.chromium.chrome.browser.segmentation_platform.ContextualPageActionController;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.share.ShareButtonController;
 import org.chromium.chrome.browser.share.ShareDelegate;
@@ -236,6 +237,7 @@
     private List<ButtonDataProvider> mButtonDataProviders;
     @Nullable
     private AdaptiveToolbarButtonController mAdaptiveToolbarButtonController;
+    private ContextualPageActionController mContextualPageActionController;
     private IdentityDiscController mIdentityDiscController;
     private ChromeActionModeHandler mChromeActionModeHandler;
     private final ToolbarActionModeCallback mActionModeControllerCallback;
@@ -541,6 +543,11 @@
             mToolbarManager = null;
         }
 
+        if (mContextualPageActionController != null) {
+            mContextualPageActionController.destroy();
+            mContextualPageActionController = null;
+        }
+
         if (mAdaptiveToolbarButtonController != null) {
             mAdaptiveToolbarButtonController.destroy();
             mAdaptiveToolbarButtonController = null;
@@ -1098,6 +1105,8 @@
                     AdaptiveToolbarButtonVariant.VOICE, voiceToolbarButtonController);
             adaptiveToolbarButtonController.addButtonVariant(
                     AdaptiveToolbarButtonVariant.PRICE_TRACKING, priceTrackingButtonController);
+            mContextualPageActionController = new ContextualPageActionController(
+                    mProfileSupplier, mActivityTabProvider, adaptiveToolbarButtonController);
             mButtonDataProviders =
                     Arrays.asList(mIdentityDiscController, adaptiveToolbarButtonController);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 9ccb1ba..60dbd9e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -105,6 +105,8 @@
 import org.chromium.chrome.browser.history.HistoryItem;
 import org.chromium.chrome.browser.history.TestBrowsingHistoryObserver;
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
+import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
+import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
 import org.chromium.chrome.browser.tab.Tab;
@@ -222,6 +224,11 @@
     public void tearDown() {
         TestThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(false));
 
+        SharedPreferencesManager.getInstance().removeKey(
+                ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION);
+        SharedPreferencesManager.getInstance().removeKey(
+                ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP);
+
         stopAndShutdownEmbeddedTestServer();
 
         // finish() is called on a non-UI thread by the testing harness. Must hide the menu
@@ -1343,6 +1350,29 @@
                 "No new spare renderer", 2000, 200);
     }
 
+    @Test
+    @SmallTest
+    @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+    @Features.EnableFeatures(ChromeFeatureList.CCT_RETAINING_STATE)
+    public void testInteractionRecordedOnClose() throws Exception {
+        Context context = InstrumentationRegistry.getInstrumentation()
+                                  .getTargetContext()
+                                  .getApplicationContext();
+        mCustomTabActivityTestRule.startCustomTabActivityWithIntent(
+                CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage));
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            final CustomTabActivity activity = mCustomTabActivityTestRule.getActivity();
+            activity.getComponent().resolveNavigationController().finish(FinishReason.OTHER);
+        });
+        CriteriaHelper.pollUiThread(
+                ()
+                        -> SharedPreferencesManager.getInstance().contains(
+                                   ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION)
+                        && SharedPreferencesManager.getInstance().contains(
+                                ChromePreferenceKeys.CUSTOM_TABS_LAST_CLOSE_TIMESTAMP));
+    }
+
     /**
      * Tests that hidden tab accepts a referrer, and that this is not lost when launching the
      * Custom Tab.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java
index 7f06505..2ee28ec 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/BackgroundMetricsTest.java
@@ -5,9 +5,9 @@
 package org.chromium.chrome.browser.metrics;
 
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
index d591d72..90dea8e2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperTest.java
@@ -5,9 +5,9 @@
 package org.chromium.chrome.browser.paint_preview;
 
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Assert;
 import org.junit.Rule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java
index e5a6e24..013c818 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/ExpandablePaymentHandlerTest.java
@@ -14,10 +14,10 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withText;
 
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 import android.view.View;
 
 import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
index 3279a4c..d1224b0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/portals/PortalsTest.java
@@ -9,15 +9,15 @@
 import android.os.Build;
 import android.service.notification.StatusBarNotification;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
 import android.text.TextUtils;
 import android.view.View;
 
 import androidx.annotation.RequiresApi;
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
 
 import org.hamcrest.Matchers;
 import org.junit.After;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
index a8aae44..83d098e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/test/ScreenShooter.java
@@ -16,7 +16,8 @@
 import android.graphics.Point;
 import android.os.Build;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.uiautomator.UiDevice;
 
 import org.json.JSONArray;
 import org.json.JSONException;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
index 8ba4bb5..9b18d3e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrVrTransitionTest.java
@@ -19,9 +19,9 @@
 import android.graphics.Color;
 import android.os.Build;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
 
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
index f59a8ed..23c6d7e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/util/VrTestRuleUtils.java
@@ -7,7 +7,8 @@
 import android.content.Intent;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
+
+import androidx.test.uiautomator.UiDevice;
 
 import org.junit.Assert;
 import org.junit.rules.RuleChain;
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java
index 2dcbfe2..7f08a64 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinatorTest.java
@@ -4,9 +4,13 @@
 
 package org.chromium.chrome.browser.history_clusters;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.Mockito.doReturn;
 
+import android.app.Activity;
 import android.content.Intent;
 import android.view.ViewGroup;
 
@@ -27,6 +31,7 @@
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
 
+import org.chromium.base.Promise;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.JniMocker;
@@ -81,6 +86,8 @@
     private ActivityScenario<ChromeTabbedActivity> mActivityScenario;
     private HistoryClustersCoordinator mHistoryClustersCoordinator;
     private Intent mIntent = new Intent();
+    private Activity mActivity;
+    private Promise mPromise = new Promise();
 
     @Before
     public void setUp() {
@@ -88,6 +95,7 @@
         jniMocker.mock(LargeIconBridgeJni.TEST_HOOKS, mMockLargeIconBridgeJni);
         doReturn(1L).when(mMockLargeIconBridgeJni).init();
         ShadowHistoryClustersBridge.sBridge = mHistoryClustersBridge;
+        doReturn(mPromise).when(mHistoryClustersBridge).queryClusters(anyString());
 
         mActivityScenario = ActivityScenario.launch(ChromeTabbedActivity.class);
         HistoryClustersDelegate historyClustersDelegate = new HistoryClustersDelegate() {
@@ -117,9 +125,11 @@
             }
         };
 
-        mActivityScenario.onActivity(activity
-                -> mHistoryClustersCoordinator = new HistoryClustersCoordinator(
-                           mProfile, activity, mTemplateUrlService, historyClustersDelegate));
+        mActivityScenario.onActivity(activity -> {
+            mActivity = activity;
+            mHistoryClustersCoordinator = new HistoryClustersCoordinator(
+                    mProfile, activity, mTemplateUrlService, historyClustersDelegate);
+        });
     }
 
     @After
@@ -140,6 +150,30 @@
         assertNotNull(toolbar);
     }
 
+    @Test
+    public void testSearchMenuItem() {
+        HistoryClustersToolbar toolbar = mHistoryClustersCoordinator.getActivityContentView()
+                                                 .findViewById(R.id.selectable_list)
+                                                 .findViewById(R.id.action_bar);
+        assertNotNull(toolbar);
+
+        mHistoryClustersCoordinator.onMenuItemClick(
+                toolbar.getMenu().findItem(R.id.search_menu_id));
+        assertTrue(toolbar.isSearching());
+    }
+
+    @Test
+    public void testCloseMenuItem() {
+        HistoryClustersToolbar toolbar = mHistoryClustersCoordinator.getActivityContentView()
+                                                 .findViewById(R.id.selectable_list)
+                                                 .findViewById(R.id.action_bar);
+        assertNotNull(toolbar);
+
+        assertFalse(mActivity.isFinishing());
+        mHistoryClustersCoordinator.onMenuItemClick(toolbar.getMenu().findItem(R.id.close_menu_id));
+        assertTrue(mActivity.isFinishing());
+    }
+
     private static void resetStaticState() {
         DisplayAndroidManager.resetInstanceForTesting();
         TabWindowManagerSingleton.resetTabModelSelectorFactoryForTesting();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
index d9e9b26..4f725e6 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiWindowUtilsUnitTest.java
@@ -139,6 +139,41 @@
         assertEquals(2, MultiWindowUtils.getInstanceCount());
     }
 
+    @Test
+    public void testGetInstanceIdForViewIntent_LesserThanMaxWindowsOpen() {
+        when(mTabModelSelector.getModel(false)).thenReturn(mNormalTabModel);
+        when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel);
+
+        int maxInstances = MultiWindowUtils.getMaxInstances();
+        // Simulate opening of 1 less than the max number of instances.
+        for (int i = 0; i < maxInstances - 1; i++) {
+            writeInstanceInfo(i, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, i + 5);
+        }
+
+        int instanceId = MultiWindowUtils.getInstanceIdForViewIntent();
+        assertEquals("The default instance ID should be returned.",
+                MultiWindowUtils.INVALID_INSTANCE_ID, instanceId);
+    }
+
+    @Test
+    public void testGetInstanceIdForViewIntent_MaxWindowsOpen() {
+        when(mTabModelSelector.getModel(false)).thenReturn(mNormalTabModel);
+        when(mTabModelSelector.getModel(true)).thenReturn(mIncognitoTabModel);
+
+        int maxInstances = MultiWindowUtils.getMaxInstances();
+        // Simulate opening of max number of instances.
+        for (int i = 0; i < maxInstances; i++) {
+            writeInstanceInfo(i, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, i + 5);
+        }
+
+        // Simulate last access of instance ID 0.
+        writeInstanceInfo(INSTANCE_ID_0, URL_1, /*tabCount=*/3, /*incognitoTabCount=*/0, TASK_ID_5);
+
+        int instanceId = MultiWindowUtils.getInstanceIdForViewIntent();
+        assertEquals(
+                "The last accessed instance ID should be returned.", INSTANCE_ID_0, instanceId);
+    }
+
     private void writeInstanceInfo(
             int instanceId, String url, int tabCount, int incognitoTabCount, int taskId) {
         MultiInstanceManagerApi31.writeUrl(instanceId, url);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java
index 4e5d3ec..7c20894 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/TabViewAndroidDelegateTest.java
@@ -11,10 +11,14 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
+import android.content.Intent;
+import android.net.Uri;
 import android.os.Build;
 import android.view.DragAndDropPermissions;
 import android.view.DragEvent;
 
+import androidx.test.core.app.ApplicationProvider;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -22,12 +26,16 @@
 import org.mockito.Mock;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
 import org.robolectric.annotation.LooperMode;
 
 import org.chromium.base.FeatureList;
 import org.chromium.base.FeatureList.TestValues;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.tab.TabViewAndroidDelegate.DragAndDropBrowserDelegateImpl;
 import org.chromium.components.embedder_support.view.ContentView;
 import org.chromium.content_public.browser.WebContents;
@@ -35,6 +43,7 @@
 import org.chromium.ui.base.ApplicationViewportInsetSupplier;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.ui.dragdrop.DragAndDropBrowserDelegate;
+import org.chromium.url.JUnitTestGURLs;
 
 /** Unit tests for the TabViewAndroidDelegate. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -82,11 +91,15 @@
         when(mTab.getWindowAndroid()).thenReturn(mWindowAndroid);
         when(mTab.getWebContents()).thenReturn(mWebContents);
         when(mTab.getContext()).thenReturn(mActivity);
+        when(mActivity.getApplicationContext())
+                .thenReturn(ApplicationProvider.getApplicationContext());
         when(mActivity.requestDragAndDropPermissions(mDragEvent))
                 .thenReturn(mDragAndDropPermissions);
 
         FeatureList.TestValues testValues = new TestValues();
         testValues.addFeatureFlagOverride(ContentFeatures.TOUCH_DRAG_AND_CONTEXT_MENU, false);
+        testValues.addFeatureFlagOverride(ChromeFeatureList.INSTANCE_SWITCHER, true);
+        testValues.addFeatureFlagOverride(ChromeFeatureList.NEW_INSTANCE_FROM_DRAGGED_LINK, true);
         FeatureList.setTestValues(testValues);
         mViewAndroidDelegate = new TabViewAndroidDelegate(mTab, mContentView);
         verify(mTab).addObserver(mTabObserverCaptor.capture());
@@ -129,7 +142,7 @@
     }
 
     @Test
-    public void testDragAndDropBrowserDelegate() {
+    public void testDragAndDropBrowserDelegate_getDragAndDropPermissions() {
         DragAndDropBrowserDelegate delegate = new DragAndDropBrowserDelegateImpl(mTab, true);
         assertTrue("SupportDropInChrome should be true.", delegate.getSupportDropInChrome());
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@@ -137,4 +150,20 @@
             assertNotNull("DragAndDropPermissions should not be null.", permissions);
         }
     }
+
+    @Test
+    @Config(sdk = 30)
+    public void testDragAndDropBrowserDelegate_createLinkIntent() {
+        DragAndDropBrowserDelegate delegate = new DragAndDropBrowserDelegateImpl(mTab, true);
+        Intent intent = delegate.createLinkIntent(JUnitTestGURLs.EXAMPLE_URL);
+        assertEquals("The intent flags should match.",
+                Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK,
+                intent.getFlags());
+        assertEquals("The intent class should be ChromeTabbedActivity.",
+                ChromeTabbedActivity.class.getName(), intent.getComponent().getClassName());
+        assertTrue("preferNew extra should be true.",
+                intent.getBooleanExtra(IntentHandler.EXTRA_PREFER_NEW, false));
+        assertEquals("The intent should contain Uri data.", Uri.parse(JUnitTestGURLs.EXAMPLE_URL),
+                intent.getData());
+    }
 }
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 47efe5f..d2928a0 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -123,6 +123,7 @@
 #define IDC_VIRTUAL_CARD_ENROLL         35032
 #define IDC_FOLLOW                      35033
 #define IDC_UNFOLLOW                    35034
+#define IDC_BASIC_PRINT_DEPRECATED      35035
 
 // Page-manipulation commands that target a specified tab, which may not be the
 // active one.
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp
index b70cab2..ae15f300 100644
--- a/chrome/app/printing_strings.grdp
+++ b/chrome/app/printing_strings.grdp
@@ -338,7 +338,7 @@
     </if>
     <if expr="not chromeos_ash and not chromeos_lacros">
       <message name="IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION" desc="Option allowing the user to access advanced printer settings using the native print system dialog instead of printing through the print preview mechanism. Shortcut key is not translated">
-        Print using system dialog... <ph name="SHORTCUT_KEY">$1<ex>(Shift+Ctrl+P)</ex></ph>
+        Print using system dialog... <ph name="SHORTCUT_KEY">$1<ex>(Ctrl+Alt+P)</ex></ph>
       </message>
     </if>
     <if expr="is_macosx">
@@ -361,4 +361,7 @@
   <message name="IDS_PRINT_SPOOL_FAILED_ERROR_TEXT" desc="Text in a messagebox when printing fails because of printer issues.">
     Something went wrong when trying to print.  Please check your printer and try again.
   </message>
+  <message name="IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT" desc="Notification to tell users about the deprecation of the Ctrl+Shift+P for printing via the system dialog. Shortcut keys are not translated">
+    This shortcut has changed. Please use <ph name="NEW_SHORTCUT_KEY">$1<ex>(Ctrl+Alt+P)</ex></ph> to print using system dialog.
+  </message>
 </grit-part>
diff --git a/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1 b/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1
new file mode 100644
index 0000000..e32a872
--- /dev/null
+++ b/chrome/app/printing_strings_grdp/IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT.png.sha1
@@ -0,0 +1 @@
+23847c4846637584e6773babe07944bec69c6ac8
\ No newline at end of file
diff --git a/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1 b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1
new file mode 100644
index 0000000..58a59de5
--- /dev/null
+++ b/chrome/app/printing_strings_grdp/IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION.png.sha1
@@ -0,0 +1 @@
+124cad2482f34af1a1492eb07be843a7bda61830
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index de3ce3f7..379d1a27 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2597,11 +2597,15 @@
       "android/cookies/cookies_fetcher_util.cc",
       "android/customtabs/client_data_header_web_contents_observer.cc",
       "android/customtabs/client_data_header_web_contents_observer.h",
+      "android/customtabs/custom_tab_session_state_tracker.cc",
+      "android/customtabs/custom_tab_session_state_tracker.h",
       "android/customtabs/custom_tabs_connection.cc",
       "android/customtabs/detached_resource_request.cc",
       "android/customtabs/detached_resource_request.h",
       "android/customtabs/origin_verifier.cc",
       "android/customtabs/origin_verifier.h",
+      "android/customtabs/tab_interaction_recorder_android.cc",
+      "android/customtabs/tab_interaction_recorder_android.h",
       "android/devtools_manager_delegate_android.cc",
       "android/devtools_manager_delegate_android.h",
       "android/devtools_server.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 38c7bb3..1dcd8f8b 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8448,6 +8448,11 @@
      flag_descriptions::kTouchDragAndContextMenuName,
      flag_descriptions::kTouchDragAndContextMenuDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(features::kTouchDragAndContextMenu)},
+
+    {"new-instance-from-dragged-link",
+     flag_descriptions::kNewInstanceFromDraggedLinkName,
+     flag_descriptions::kNewInstanceFromDraggedLinkDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kNewInstanceFromDraggedLink)},
 #endif  // BUILDFLAG(IS_ANDROID)
 
     {"autofill-enable-update-virtual-card-enrollment",
diff --git a/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc
new file mode 100644
index 0000000..82c57db
--- /dev/null
+++ b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.cc
@@ -0,0 +1,64 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/customtabs/custom_tab_session_state_tracker.h"
+
+#include "base/android/jni_string.h"
+#include "chrome/android/chrome_jni_headers/CustomTabsOpenTimeRecorder_jni.h"
+
+namespace chrome {
+namespace android {
+
+// static
+CustomTabSessionStateTracker& CustomTabSessionStateTracker::GetInstance() {
+  static base::NoDestructor<CustomTabSessionStateTracker> instance;
+  return *instance;
+}
+
+bool CustomTabSessionStateTracker::HasCustomTabSessionState() const {
+  return has_custom_tab_session_;
+}
+
+void CustomTabSessionStateTracker::RecordCustomTabSession(
+    int64_t time_sec,
+    std::string package_name,
+    int32_t session_duration,
+    bool was_user_closed,
+    bool is_partial) {
+  has_custom_tab_session_ = true;
+  custom_tab_session_ = std::make_unique<metrics::CustomTabSessionProto>();
+  custom_tab_session_->set_time_sec(time_sec);
+  custom_tab_session_->set_package_name(package_name);
+  custom_tab_session_->set_session_duration_sec(session_duration);
+  // TODO(crbug.com/1334500): add set_did_user_interact as well.
+  custom_tab_session_->set_was_user_closed(was_user_closed);
+  custom_tab_session_->set_is_partial(is_partial);
+}
+
+std::unique_ptr<metrics::CustomTabSessionProto>
+CustomTabSessionStateTracker::GetSession() {
+  // Clear the session because we only want the state recorded once.
+  has_custom_tab_session_ = false;
+
+  return std::move(custom_tab_session_);
+}
+
+CustomTabSessionStateTracker::CustomTabSessionStateTracker() = default;
+CustomTabSessionStateTracker::~CustomTabSessionStateTracker() = default;
+
+}  // namespace android
+}  // namespace chrome
+
+static void JNI_CustomTabsOpenTimeRecorder_RecordCustomTabSession(
+    JNIEnv* env,
+    jlong j_time,
+    const base::android::JavaParamRef<jstring>& j_package_name,
+    jlong j_session_duration,
+    jboolean j_was_user_closed,
+    jboolean j_is_partial_cct) {
+  std::string package_name = ConvertJavaStringToUTF8(env, j_package_name);
+  chrome::android::CustomTabSessionStateTracker::GetInstance()
+      .RecordCustomTabSession(j_time, package_name, j_session_duration,
+                              j_was_user_closed, j_is_partial_cct);
+}
diff --git a/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h
new file mode 100644
index 0000000..6a69571
--- /dev/null
+++ b/chrome/browser/android/customtabs/custom_tab_session_state_tracker.h
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_
+#define CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_
+
+#include "base/feature_list.h"
+#include "base/no_destructor.h"
+#include "third_party/metrics_proto/custom_tab_session.pb.h"
+
+namespace chrome {
+namespace android {
+
+// This is a singleton.
+class CustomTabSessionStateTracker {
+ public:
+  static CustomTabSessionStateTracker& GetInstance();
+
+  CustomTabSessionStateTracker(const CustomTabSessionStateTracker&) = delete;
+  CustomTabSessionStateTracker& operator=(const CustomTabSessionStateTracker&) =
+      delete;
+
+  void RecordCustomTabSession(int64_t time_sec,
+                              std::string package_name,
+                              int32_t session_duration,
+                              bool was_user_closed,
+                              bool is_partial);
+
+  bool HasCustomTabSessionState() const;
+  std::unique_ptr<metrics::CustomTabSessionProto> GetSession();
+
+ private:
+  friend class base::NoDestructor<CustomTabSessionStateTracker>;
+
+  CustomTabSessionStateTracker();
+  ~CustomTabSessionStateTracker();
+
+  bool has_custom_tab_session_;
+
+  std::unique_ptr<metrics::CustomTabSessionProto> custom_tab_session_;
+};
+
+}  // namespace android
+}  // namespace chrome
+
+#endif  // CHROME_BROWSER_ANDROID_CUSTOMTABS_CUSTOM_TAB_SESSION_STATE_TRACKER_H_
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
new file mode 100644
index 0000000..861a07b
--- /dev/null
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.cc
@@ -0,0 +1,159 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/customtabs/tab_interaction_recorder_android.h"
+
+#include <memory>
+
+#include "base/android/jni_android.h"
+#include "base/bind.h"
+#include "base/memory/raw_ptr.h"
+#include "chrome/android/chrome_jni_headers/TabInteractionRecorder_jni.h"
+#include "chrome/browser/android/tab_android.h"
+#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "content/public/browser/global_routing_id.h"
+#include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+
+namespace customtabs {
+
+using autofill::AutofillManager;
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+using content::RenderFrameHost;
+
+namespace {
+
+// static
+AutofillManager* GetAutofillManager(RenderFrameHost* render_frame_host) {
+  auto* autofill_driver =
+      autofill::ContentAutofillDriver::GetForRenderFrameHost(render_frame_host);
+  if (!autofill_driver)
+    return nullptr;
+  return autofill_driver->autofill_manager();
+}
+}  // namespace
+
+AutofillObserverImpl::AutofillObserverImpl(
+    autofill::AutofillManager* autofill_manager,
+    OnFormInteractionCallback form_interaction_callback)
+    : autofill_manager_(autofill_manager),
+      form_interaction_callback_(std::move(form_interaction_callback)) {
+  autofill_manager->AddObserver(this);
+}
+
+AutofillObserverImpl::~AutofillObserverImpl() = default;
+
+void AutofillObserverImpl::OnFormSubmitted() {
+  OnFormInteraction();
+}
+
+void AutofillObserverImpl::OnSelectControlDidChange() {
+  OnFormInteraction();
+}
+
+void AutofillObserverImpl::OnTextFieldDidChange() {
+  OnFormInteraction();
+}
+
+void AutofillObserverImpl::OnTextFieldDidScroll() {
+  OnFormInteraction();
+}
+
+void AutofillObserverImpl::OnFormInteraction() {
+  DCHECK(autofill_manager_);
+  autofill_manager_->RemoveObserver(this);
+  autofill_manager_ = nullptr;
+  std::move(form_interaction_callback_).Run();
+}
+
+TabInteractionRecorderAndroid::~TabInteractionRecorderAndroid() = default;
+
+TabInteractionRecorderAndroid::TabInteractionRecorderAndroid(
+    content::WebContents* web_contents)
+    : content::WebContentsObserver(web_contents),
+      content::WebContentsUserData<TabInteractionRecorderAndroid>(
+          *web_contents) {}
+
+bool TabInteractionRecorderAndroid::HasNavigatedFromFirstPage() const {
+  return web_contents()->GetController().CanGoBack() ||
+         web_contents()->GetController().CanGoForward();
+}
+
+// content::WebContentsObserver:
+void TabInteractionRecorderAndroid::RenderFrameHostStateChanged(
+    RenderFrameHost* render_frame_host,
+    RenderFrameHost::LifecycleState old_state,
+    RenderFrameHost::LifecycleState new_state) {
+  if (old_state == RenderFrameHost::LifecycleState::kActive) {
+    rfh_observer_map_.erase(render_frame_host->GetGlobalId());
+  } else if (new_state == RenderFrameHost::LifecycleState::kActive &&
+             !has_form_interactions_) {
+    StartObservingFrame(render_frame_host);
+  }
+}
+
+void TabInteractionRecorderAndroid::DidFinishNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (has_form_interactions_)
+    return;
+  if (!navigation_handle->IsSameDocument() &&
+      navigation_handle->HasCommitted() &&
+      navigation_handle->GetRenderFrameHost()->IsActive())
+    StartObservingFrame(navigation_handle->GetRenderFrameHost());
+}
+
+void TabInteractionRecorderAndroid::SetHasFormInteractions() {
+  has_form_interactions_ = true;
+  rfh_observer_map_.clear();
+}
+
+void TabInteractionRecorderAndroid::StartObservingFrame(
+    RenderFrameHost* render_frame_host) {
+  AutofillManager* autofill_manager =
+      test_autofill_manager_ ? test_autofill_manager_.get()
+                             : GetAutofillManager(render_frame_host);
+  if (!autofill_manager)
+    return;
+
+  rfh_observer_map_[render_frame_host->GetGlobalId()] =
+      std::make_unique<AutofillObserverImpl>(
+          autofill_manager,
+          base::BindOnce(&TabInteractionRecorderAndroid::SetHasFormInteractions,
+                         weak_factory_.GetWeakPtr()));
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(TabInteractionRecorderAndroid);
+
+// JNI methods
+jboolean TabInteractionRecorderAndroid::HadInteraction(JNIEnv* env) const {
+  bool has_interaction = has_form_interactions() || HasNavigatedFromFirstPage();
+  return static_cast<jboolean>(has_interaction);
+}
+
+ScopedJavaLocalRef<jobject> JNI_TabInteractionRecorder_GetFromTab(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& jtab) {
+  TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
+  auto* recorder =
+      TabInteractionRecorderAndroid::FromWebContents(tab->web_contents());
+  return Java_TabInteractionRecorder_create(
+      env, reinterpret_cast<int64_t>(recorder));
+}
+
+ScopedJavaLocalRef<jobject> JNI_TabInteractionRecorder_CreateForTab(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& jtab) {
+  TabAndroid* tab = TabAndroid::GetNativeTab(env, jtab);
+  TabInteractionRecorderAndroid::CreateForWebContents(tab->web_contents());
+
+  auto* recorder =
+      TabInteractionRecorderAndroid::FromWebContents(tab->web_contents());
+  return Java_TabInteractionRecorder_create(
+      env, reinterpret_cast<int64_t>(recorder));
+}
+
+}  // namespace customtabs
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android.h b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
new file mode 100644
index 0000000..3acba528
--- /dev/null
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android.h
@@ -0,0 +1,107 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_
+#define CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_
+
+#include "base/android/jni_android.h"
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "url/gurl.h"
+
+namespace customtabs {
+
+// Autofill observer impl for the TabInteractionRecorderAndroid to use.
+class AutofillObserverImpl : public autofill::AutofillManager::Observer {
+ public:
+  using OnFormInteractionCallback = base::OnceCallback<void()>;
+
+  explicit AutofillObserverImpl(
+      autofill::AutofillManager* autofill_manager,
+      OnFormInteractionCallback form_interaction_callback);
+
+  AutofillObserverImpl(const AutofillObserverImpl&) = delete;
+  AutofillObserverImpl operator=(const AutofillObserverImpl&) = delete;
+  ~AutofillObserverImpl() override;
+
+  // AutofillManager::Observer:
+  void OnFormSubmitted() override;
+  void OnSelectControlDidChange() override;
+  void OnTextFieldDidChange() override;
+  void OnTextFieldDidScroll() override;
+
+ private:
+  void OnFormInteraction();
+
+  raw_ptr<autofill::AutofillManager> autofill_manager_;
+  OnFormInteractionCallback form_interaction_callback_;
+};
+
+// Class that record interaction from the web contents. The definition
+// of an "interaction" includes user's engagement with text inputs or selection
+// inputs, or changes in navigation stacks.
+//
+// To attach this class to the web contents correctly, it has to be setup
+// before the first navigation finishes in order to attach observers to
+// corresponding autofill managers; otherwise the interaction with first frame
+// would be missing.
+class TabInteractionRecorderAndroid
+    : public content::WebContentsObserver,
+      public content::WebContentsUserData<TabInteractionRecorderAndroid> {
+ public:
+  ~TabInteractionRecorderAndroid() override;
+
+  // Return whether the |web_contents()| has navigated away from the first page.
+  bool HasNavigatedFromFirstPage() const;
+
+  // Return whether the |web_contents()| has seen any form interactions.
+  bool has_form_interactions() const { return has_form_interactions_; }
+
+  // content::WebContentsObserver:
+  void RenderFrameHostStateChanged(
+      content::RenderFrameHost* render_frame_host,
+      content::RenderFrameHost::LifecycleState old_state,
+      content::RenderFrameHost::LifecycleState new_state) override;
+  void DidFinishNavigation(
+      content::NavigationHandle* navigation_handle) override;
+
+  // JNI methods
+  jboolean HadInteraction(JNIEnv* env) const;
+
+#ifdef UNIT_TEST
+  void SetAutofillManagerForTest(
+      autofill::AutofillManager* test_autofill_manager) {
+    test_autofill_manager_ = test_autofill_manager;
+  }
+#endif
+
+ private:
+  explicit TabInteractionRecorderAndroid(content::WebContents* web_contents);
+
+  friend class AutofillObserverImpl;
+  void StartObservingFrame(content::RenderFrameHost* render_frame_host);
+  void SetHasFormInteractions();
+
+  bool has_form_interactions_ = false;
+  std::unordered_map<content::GlobalRenderFrameHostId,
+                     std::unique_ptr<AutofillObserverImpl>,
+                     content::GlobalRenderFrameHostIdHasher>
+      rfh_observer_map_;
+  raw_ptr<autofill::AutofillManager> test_autofill_manager_ = nullptr;
+
+  // content::WebContentsUserData<TabInteractionRecorderAndroid>
+  friend class content::WebContentsUserData<TabInteractionRecorderAndroid>;
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+  base::WeakPtrFactory<TabInteractionRecorderAndroid> weak_factory_{this};
+};
+
+}  // namespace customtabs
+
+#endif  // CHROME_BROWSER_ANDROID_CUSTOMTABS_TAB_INTERACTION_RECORDER_ANDROID_H_
diff --git a/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
new file mode 100644
index 0000000..c62365d1
--- /dev/null
+++ b/chrome/browser/android/customtabs/tab_interaction_recorder_android_unittest.cc
@@ -0,0 +1,183 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/android/customtabs/tab_interaction_recorder_android.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/test/mock_callback.h"
+#include "chrome/browser/ui/tab_helpers.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/content/browser/content_autofill_driver_factory_test_api.h"
+#include "components/autofill/content/browser/content_autofill_driver_test_api.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/autofill_test_utils.h"
+#include "components/autofill/core/browser/test_autofill_client.h"
+#include "components/autofill/core/browser/test_autofill_driver.h"
+#include "components/autofill/core/browser/test_browser_autofill_manager.h"
+#include "components/autofill/core/common/autofill_tick_clock.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using autofill::AutofillManager;
+using testing::_;
+using testing::NiceMock;
+using AutofillObsever = AutofillManager::Observer;
+
+namespace customtabs {
+
+namespace {
+class MockAutofillClient : public autofill::TestAutofillClient {
+ public:
+  MockAutofillClient() = default;
+  MockAutofillClient(const MockAutofillClient&) = delete;
+  MockAutofillClient& operator=(const MockAutofillClient&) = delete;
+  ~MockAutofillClient() override = default;
+};
+
+class MockAutofillDriver : public autofill::TestAutofillDriver {
+ public:
+  MockAutofillDriver() = default;
+  MockAutofillDriver(const MockAutofillDriver&) = delete;
+  MockAutofillDriver& operator=(const MockAutofillDriver&) = delete;
+  ~MockAutofillDriver() override = default;
+};
+
+class MockAutofillManager : public autofill::TestBrowserAutofillManager {
+ public:
+  MockAutofillManager(autofill::TestAutofillDriver* driver,
+                      autofill::TestAutofillClient* client)
+      : autofill::TestBrowserAutofillManager(driver, client) {}
+  MockAutofillManager(const MockAutofillManager&) = delete;
+  MockAutofillManager& operator=(const MockAutofillManager&) = delete;
+  ~MockAutofillManager() override = default;
+};
+
+void OnTextFieldDidChangeForAutofillManager(AutofillManager* autofill_manager) {
+  autofill::FormData form;
+  autofill::test::CreateTestAddressFormData(&form);
+  autofill::FormFieldData field = form.fields.front();
+
+  autofill_manager->OnTextFieldDidChange(
+      form, field, gfx::RectF(), autofill::AutofillTickClock::NowTicks());
+}
+}  // namespace
+
+class AutofillObserverImplTest : public testing::Test {
+ public:
+  AutofillObserverImplTest() = default;
+
+  void SetUp() override {
+    client_.SetPrefs(autofill::test::PrefServiceForTesting());
+    driver_ = std::make_unique<NiceMock<MockAutofillDriver>>();
+    manager_ = std::make_unique<MockAutofillManager>(driver_.get(), &client_);
+  }
+
+  void TearDown() override {
+    manager_.reset();
+    driver_.reset();
+  }
+
+  MockAutofillManager* autofill_manager() { return manager_.get(); }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  NiceMock<MockAutofillClient> client_;
+  std::unique_ptr<MockAutofillDriver> driver_;
+  std::unique_ptr<MockAutofillManager> manager_;
+};
+
+TEST_F(AutofillObserverImplTest, TestFormInteraction) {
+  base::MockOnceCallback<void()> callback;
+  AutofillObserverImpl obsever(autofill_manager(), callback.Get());
+
+  EXPECT_CALL(callback, Run()).Times(1);
+  OnTextFieldDidChangeForAutofillManager(autofill_manager());
+
+  // Observer should no longer get notified after the first interaction.
+  EXPECT_CALL(callback, Run()).Times(0);
+  OnTextFieldDidChangeForAutofillManager(autofill_manager());
+}
+
+TEST_F(AutofillObserverImplTest, TestNoFormInteraction) {
+  base::MockOnceCallback<void()> callback;
+  auto* observer = new AutofillObserverImpl(autofill_manager(), callback.Get());
+
+  EXPECT_CALL(callback, Run()).Times(0);
+  delete observer;
+}
+
+// === TabInteractionRecorderAndroidTest ===
+
+class TabInteractionRecorderAndroidTest
+    : public ChromeRenderViewHostTestHarness {
+ public:
+  TabInteractionRecorderAndroidTest() = default;
+
+  void SetUp() override {
+    ChromeRenderViewHostTestHarness::SetUp();
+
+    client_.SetPrefs(autofill::test::PrefServiceForTesting());
+    driver_ = std::make_unique<NiceMock<MockAutofillDriver>>();
+    manager_ = std::make_unique<MockAutofillManager>(driver_.get(), &client_);
+  }
+
+  void TearDown() override {
+    manager_.reset();
+    driver_.reset();
+    ChromeRenderViewHostTestHarness::TearDown();
+  }
+
+  std::unique_ptr<content::WebContents> CreateTestWebContents() {
+    std::unique_ptr<content::WebContents> contents =
+        ChromeRenderViewHostTestHarness::CreateTestWebContents();
+    TabInteractionRecorderAndroid::CreateForWebContents(contents.get());
+    auto* helper =
+        TabInteractionRecorderAndroid::FromWebContents(contents.get());
+    helper->SetAutofillManagerForTest(autofill_manager());
+
+    // Simulate a navigation event to force the initialization of the main
+    // frame.
+    content::WebContentsTester::For(contents.get())
+        ->NavigateAndCommit(GURL("https://foo.com"));
+    task_environment()->RunUntilIdle();
+    return contents;
+  }
+
+  MockAutofillManager* autofill_manager() { return manager_.get(); }
+
+ protected:
+  NiceMock<MockAutofillClient> client_;
+  std::unique_ptr<MockAutofillDriver> driver_;
+  std::unique_ptr<MockAutofillManager> manager_;
+};
+
+TEST_F(TabInteractionRecorderAndroidTest, HadFormInteraction) {
+  std::unique_ptr<content::WebContents> contents = CreateTestWebContents();
+  auto* helper = TabInteractionRecorderAndroid::FromWebContents(contents.get());
+
+  EXPECT_FALSE(helper->has_form_interactions());
+  OnTextFieldDidChangeForAutofillManager(autofill_manager());
+  EXPECT_TRUE(helper->has_form_interactions());
+}
+
+TEST_F(TabInteractionRecorderAndroidTest, HasNavigatedFromFirstPage) {
+  std::unique_ptr<content::WebContents> contents = CreateTestWebContents();
+  auto* helper = TabInteractionRecorderAndroid::FromWebContents(contents.get());
+
+  EXPECT_FALSE(helper->HasNavigatedFromFirstPage());
+
+  content::WebContentsTester::For(contents.get())
+      ->NavigateAndCommit(GURL("https://bar.com"));
+  task_environment()->RunUntilIdle();
+  EXPECT_TRUE(helper->HasNavigatedFromFirstPage());
+}
+
+}  // namespace customtabs
diff --git a/chrome/browser/app_controller_mac.h b/chrome/browser/app_controller_mac.h
index 2e666b3..01cd02d 100644
--- a/chrome/browser/app_controller_mac.h
+++ b/chrome/browser/app_controller_mac.h
@@ -20,6 +20,7 @@
 #include "components/prefs/pref_change_registrar.h"
 
 class AppControllerProfileObserver;
+class AppControllerNativeThemeObserver;
 @class AppShimMenuController;
 class BookmarkMenuBridge;
 class CommandUpdater;
@@ -35,7 +36,7 @@
 class TabMenuBridge;
 
 namespace ui {
-class ThemeProvider;
+class ColorProvider;
 }  // namespace ui
 
 // The application controller object, created by loading the MainMenu nib.
@@ -59,6 +60,10 @@
   std::unique_ptr<AppControllerProfileObserver>
       _profileAttributesStorageObserver;
 
+  // The NativeThemeObserver observes system-wide theme related settings
+  // change.
+  std::unique_ptr<AppControllerNativeThemeObserver> _nativeThemeObserver;
+
   // Management of the bookmark menu which spans across all windows
   // (and Browser*s). |profileBookmarkMenuBridgeMap_| is a cache that owns one
   // pointer to a BookmarkMenuBridge for each profile. |bookmarkMenuBridge_| is
@@ -115,6 +120,8 @@
 
   // Request to keep the browser alive during that object's lifetime.
   std::unique_ptr<ScopedKeepAlive> _keep_alive;
+
+  const ui::ColorProvider* _lastActiveColorProvider;
 }
 
 @property(readonly, nonatomic) BOOL startupComplete;
@@ -196,9 +203,11 @@
 // the original or the incognito profile.
 - (void)setLastProfile:(Profile*)profile;
 
-// Returns the last active ThemeProvider. It is only valid to call this with a
-// last available profile.
-- (const ui::ThemeProvider&)lastActiveThemeProvider;
+// Returns the last active ColorProvider.
+- (const ui::ColorProvider&)lastActiveColorProvider;
+
+// This is called when the system wide light or dark mode changes.
+- (void)nativeThemeDidChange;
 
 // Certain NSMenuItems [Close Tab and Close Window] have different
 // keyEquivalents depending on context. This must be invoked in two locations:
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm
index 9163dc8..78a2ae8 100644
--- a/chrome/browser/app_controller_mac.mm
+++ b/chrome/browser/app_controller_mac.mm
@@ -57,7 +57,6 @@
 #include "chrome/browser/sessions/session_service.h"
 #include "chrome/browser/sessions/session_service_factory.h"
 #include "chrome/browser/sessions/tab_restore_service_factory.h"
-#include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_command_controller.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -112,6 +111,8 @@
 #include "net/base/mac/url_conversions.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/native_theme/native_theme_mac.h"
+#include "ui/native_theme/native_theme_observer.h"
 #include "url/gurl.h"
 
 namespace {
@@ -512,6 +513,25 @@
   AppController* const app_controller_;  // Weak; owns us.
 };
 
+class AppControllerNativeThemeObserver : public ui::NativeThemeObserver {
+ public:
+  AppControllerNativeThemeObserver(AppController* app_controller)
+      : app_controller_(app_controller) {
+    native_theme_observation_.Observe(
+        ui::NativeThemeMac::GetInstanceForNativeUi());
+  }
+
+  // NativeThemeObserver:
+  void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override {
+    [app_controller_ nativeThemeDidChange];
+  }
+
+ private:
+  base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
+      native_theme_observation_{this};
+  AppController* const app_controller_;  // Weak; owns us.
+};
+
 @implementation AppController
 
 @synthesize startupComplete = _startupComplete;
@@ -761,6 +781,7 @@
     profile = profile->GetOriginalProfile();
   }
   [self setLastProfile:profile];
+  _lastActiveColorProvider = browser->window()->GetColorProvider();
 }
 
 - (void)activeSpaceDidChange:(NSNotification*)notify {
@@ -882,6 +903,10 @@
       std::make_unique<AppControllerProfileObserver>(
           g_browser_process->profile_manager(), self);
 
+  // Observe native theme change (e.g. light and dark mode).
+  _nativeThemeObserver =
+      std::make_unique<AppControllerNativeThemeObserver>(self);
+
   // Record the path to the (browser) app bundle; this is used by the app mode
   // shim.
   if (base::mac::AmIBundled()) {
@@ -902,8 +927,11 @@
 
   Browser* browser = chrome::FindLastActive();
   content::WebContents* activeWebContents = nullptr;
-  if (browser)
+  _lastActiveColorProvider = nullptr;
+  if (browser) {
     activeWebContents = browser->tab_strip_model()->GetActiveWebContents();
+    _lastActiveColorProvider = browser->window()->GetColorProvider();
+  }
   [self updateHandoffManager:activeWebContents];
   [self openStartupUrls];
 
@@ -1726,14 +1754,14 @@
                           _menuState.get(), _lastProfile));
 }
 
-- (const ui::ThemeProvider&)lastActiveThemeProvider {
-  // Themes are only available while a profile is available.
-  DCHECK(_lastProfile);
+- (const ui::ColorProvider&)lastActiveColorProvider {
+  DCHECK(_lastActiveColorProvider);
+  return *_lastActiveColorProvider;
+}
 
-  // AppController is conceptually a root for Chromium Mac. As a result, it is
-  // allowed to refer to the profile to get a theme provider. Non-root UI
-  // concepts should rely on well known roots to obtain a ThemeProvider.
-  return ThemeService::GetThemeProviderForProfile(_lastProfile);
+- (void)nativeThemeDidChange {
+  Browser* browser = chrome::FindBrowserWithProfile(_lastProfile);
+  _lastActiveColorProvider = browser->window()->GetColorProvider();
 }
 
 - (BOOL)windowHasBrowserTabs:(NSWindow*)window {
@@ -1899,6 +1927,8 @@
 
 - (void)setLastProfileForTesting:(Profile*)profile {
   _lastProfile = profile;
+  Browser* browser = chrome::FindLastActiveWithProfile(profile);
+  _lastActiveColorProvider = browser->window()->GetColorProvider();
 }
 
 @end  // @implementation AppController
diff --git a/chrome/browser/apps/app_service/web_contents_app_id_utils.cc b/chrome/browser/apps/app_service/web_contents_app_id_utils.cc
index 4ecc726..596725e7 100644
--- a/chrome/browser/apps/app_service/web_contents_app_id_utils.cc
+++ b/chrome/browser/apps/app_service/web_contents_app_id_utils.cc
@@ -163,7 +163,6 @@
       extensions::ExtensionRegistry::Get(profile)->GetInstalledExtension(
           app_id);
   if (extension) {
-    DCHECK(extension->is_app());
     return true;
   }
   return IsAppReady(profile, app_id);
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc
index d3e1f143..8800c48 100644
--- a/chrome/browser/ash/accessibility/dictation_browsertest.cc
+++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -1168,6 +1168,20 @@
         /*script=*/script);
   }
 
+  void RunHiddenMacroWithStringArg(int macro, const std::string& arg) {
+    std::string script = base::StringPrintf(R"(
+      accessibilityCommon.dictation_.
+          runHiddenMacroWithStringArgForTesting(%d, "%s");
+      window.domAutomationController.send("done");
+    )",
+                                            macro, arg.c_str());
+
+    extensions::browsertest_util::ExecuteScriptInBackgroundPage(
+        /*context=*/browser()->profile(),
+        /*extension_id=*/extension_misc::kAccessibilityCommonExtensionId,
+        /*script=*/script);
+  }
+
   void RunMacroAndWaitForCaretBoundsChanged(int macro) {
     content::AccessibilityNotificationWaiter selection_waiter(
         browser()->tab_strip_model()->GetActiveWebContents(),
@@ -1305,6 +1319,60 @@
   SendFinalResultAndWaitForTextAreaValue("folks!", "This is a pop quiz folks!");
 }
 
+IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest, SmartDeletePhraseSimple) {
+  ToggleDictationWithKeystroke();
+  WaitForRecognitionStarted();
+  SendFinalResultAndWaitForTextAreaValue("This is a difficult test",
+                                         "This is a difficult test");
+  RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "difficult");
+  WaitForTextAreaValue("This is a test");
+}
+
+IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest,
+                       SmartDeletePhraseCaseInsensitive) {
+  ToggleDictationWithKeystroke();
+  WaitForRecognitionStarted();
+  SendFinalResultAndWaitForTextAreaValue("This is a DIFFICULT test",
+                                         "This is a DIFFICULT test");
+  RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "difficult");
+  WaitForTextAreaValue("This is a test");
+}
+
+IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest,
+                       SmartDeletePhraseDuplicateMatches) {
+  ToggleDictationWithKeystroke();
+  WaitForRecognitionStarted();
+  SendFinalResultAndWaitForTextAreaValue("The cow jumped over the moon.",
+                                         "The cow jumped over the moon.");
+  // Deletes the right-most occurrence of "the".
+  RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "the");
+  WaitForTextAreaValue("The cow jumped over moon.");
+}
+
+IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest,
+                       SmartDeletePhraseDeletesLeftOfCaret) {
+  ToggleDictationWithKeystroke();
+  WaitForRecognitionStarted();
+  SendFinalResultAndWaitForTextAreaValue("The cow jumped over the moon.",
+                                         "The cow jumped over the moon.");
+  RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20);
+  RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20);
+  RunMacroAndWaitForCaretBoundsChanged(/*NAV_PREV_WORD*/ 20);
+  RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "the");
+  WaitForTextAreaValue("cow jumped over the moon.");
+}
+
+IN_PROC_BROWSER_TEST_P(DictationHiddenMacrosTest,
+                       SmartDeletePhraseDeletesAtWordBoundaries) {
+  ToggleDictationWithKeystroke();
+  WaitForRecognitionStarted();
+  SendFinalResultAndWaitForTextAreaValue("A square is also a rectangle.",
+                                         "A square is also a rectangle.");
+  // Deletes the first word "a", not the first character "a".
+  RunHiddenMacroWithStringArg(/* SMART_DELETE_PHRASE */ 21, "a");
+  WaitForTextAreaValue("A square is also rectangle.");
+}
+
 // Tests behavior of Dictation and installation of Pumpkin.
 class DictationPumpkinInstallTest : public DictationTest {
  protected:
diff --git a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
index 5282a81..432eec7 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
@@ -25,6 +25,7 @@
 constexpr int kSideInset = 24;
 constexpr int kTopMargin = 24;
 constexpr int kMinHeight = 72;
+constexpr int kMaxTextWidth = 256;
 constexpr SkColor kTextColor = gfx::kGoogleGrey200;
 constexpr SkColor kBackgroundColor = gfx::kGoogleGrey900;
 constexpr SkColor kForegroundColor = SkColorSetA(SK_ColorWHITE, 0x0F);
@@ -88,8 +89,10 @@
   }
 
   auto preferred_size = CalculatePreferredSize();
-  preferred_size.SetSize(preferred_size.width() + kIconSize + kImageLabelSpace,
-                         kMinHeight);
+  preferred_size.SetSize(
+      std::min(preferred_size.width() + kIconSize + kImageLabelSpace,
+               kMaxTextWidth + kIconSize + kImageLabelSpace + 2 * kSideInset),
+      kMinHeight);
   preferred_size.SetToMin(parent_size);
   SetSize(preferred_size);
   SetPosition(gfx::Point(
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.cc b/chrome/browser/ash/crosapi/browser_data_migrator.cc
index a81bf51..1bd8d5e 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator.cc
@@ -325,15 +325,21 @@
 
   local_state->CommitPendingWrite();
 
+  const bool is_move = base::FeatureList::IsEnabled(
+                           ash::features::kLacrosMoveProfileMigration) ||
+                       MoveMigrator::ResumeRequired(local_state, user_id_hash);
+
   // TODO(crbug.com/1277848): Once `BrowserDataMigrator` stabilises, remove
   // this log message.
   LOG(WARNING) << "Making a dbus method call to session_manager";
   bool success = SessionManagerClient::Get()->RequestBrowserDataMigration(
-      cryptohome::CreateAccountIdentifierFromAccountId(account_id));
+      cryptohome::CreateAccountIdentifierFromAccountId(account_id), is_move);
 
   // TODO(crbug.com/1261730): Add an UMA.
-  if (!success)
+  if (!success) {
+    LOG(ERROR) << "SessionManagerClient::RequestBrowserDataMigration() failed.";
     return false;
+  }
 
   AttemptRestart();
   return true;
@@ -358,7 +364,8 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void BrowserDataMigratorImpl::Migrate(MigrateCallback callback) {
+void BrowserDataMigratorImpl::Migrate(crosapi::browser_util::MigrationMode mode,
+                                      MigrateCallback callback) {
   DCHECK(local_state_);
   DCHECK(completion_callback_.is_null());
   completion_callback_ = std::move(callback);
@@ -370,24 +377,25 @@
   DCHECK(GetMigrationStep(local_state_) == MigrationStep::kRestartCalled);
   SetMigrationStep(local_state_, MigrationStep::kStarted);
 
-  if (base::FeatureList::IsEnabled(
-          ash::features::kLacrosMoveProfileMigration) ||
-      MoveMigrator::ResumeRequired(local_state_, user_id_hash_)) {
-    LOG(WARNING) << "Initializing MoveMigrator.";
-    migrator_delegate_ = std::make_unique<MoveMigrator>(
-        original_profile_dir_, user_id_hash_, std::move(progress_tracker_),
-        cancel_flag_, local_state_,
-        base::BindOnce(
-            &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread,
-            weak_factory_.GetWeakPtr()));
-  } else {
-    LOG(WARNING) << "Initializing CopyMigrator.";
-    migrator_delegate_ = std::make_unique<CopyMigrator>(
-        original_profile_dir_, user_id_hash_, std::move(progress_tracker_),
-        cancel_flag_,
-        base::BindOnce(
-            &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread,
-            weak_factory_.GetWeakPtr()));
+  switch (mode) {
+    case crosapi::browser_util::MigrationMode::kMove:
+      LOG(WARNING) << "Initializing MoveMigrator.";
+      migrator_delegate_ = std::make_unique<MoveMigrator>(
+          original_profile_dir_, user_id_hash_, std::move(progress_tracker_),
+          cancel_flag_, local_state_,
+          base::BindOnce(
+              &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread,
+              weak_factory_.GetWeakPtr()));
+      break;
+    case crosapi::browser_util::MigrationMode::kCopy:
+      LOG(WARNING) << "Initializing CopyMigrator.";
+      migrator_delegate_ = std::make_unique<CopyMigrator>(
+          original_profile_dir_, user_id_hash_, std::move(progress_tracker_),
+          cancel_flag_,
+          base::BindOnce(
+              &BrowserDataMigratorImpl::MigrateInternalFinishedUIThread,
+              weak_factory_.GetWeakPtr()));
+      break;
   }
 
   migrator_delegate_->Migrate();
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator.h b/chrome/browser/ash/crosapi/browser_data_migrator.h
index 1d066666..5ed2619 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator.h
+++ b/chrome/browser/ash/crosapi/browser_data_migrator.h
@@ -77,9 +77,11 @@
 
   virtual ~BrowserDataMigrator() = default;
 
-  // Carries out the migration. It needs to be called on UI thread.
-  // |callback| will be called on the end of the migration procedure.
-  virtual void Migrate(MigrateCallback callback) = 0;
+  // Carries out the migration with the mode specified by `MigrationMode`. It
+  // needs to be called on UI thread. |callback| will be called on the end of
+  // the migration procedure.
+  virtual void Migrate(crosapi::browser_util::MigrationMode mode,
+                       MigrateCallback callback) = 0;
 
   // Cancels the migration. This should be called on UI thread.
   // If this is called during the migration, it is expected that |callback|
@@ -117,17 +119,6 @@
     Result data_migration_result;
   };
 
-  // Specifies the mode of migration.
-  enum class Mode {
-    kCopy = 0,  // Copies browser related files to lacros.
-    kMove = 1,  // Moves browser related files to lacros while copying files
-                // that are needed by both ash and lacros.
-    kDeleteAndCopy = 2,  // Similar to kCopy but deletes
-                         // TargetInfo::no_copy_items to make extra space.
-    kDeleteAndMove = 3   // Similar to kMove but deletes
-                         // TargetInfo::no_copy_items to make extra space.
-  };
-
   // Delegate interface which is responsible for the actual task of setting up
   // the profile directories for ash and lacros. The class should call
   // `MigrateInternalFinishedUIThread()` once migration is completed.
@@ -187,7 +178,8 @@
       base::OnceCallback<void(bool, const absl::optional<uint64_t>&)> callback);
 
   // `BrowserDataMigrator` methods.
-  void Migrate(MigrateCallback callback) override;
+  void Migrate(crosapi::browser_util::MigrationMode mode,
+               MigrateCallback callback) override;
   void Cancel() override;
 
   // Registers boolean pref `kCheckForMigrationOnRestart` with default as false.
diff --git a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
index 56a701d..ec816f0 100644
--- a/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
+++ b/chrome/browser/ash/crosapi/browser_data_migrator_unittest.cc
@@ -99,8 +99,10 @@
       std::make_unique<BrowserDataMigratorImpl>(
           from_dir_, user_id_hash, base::DoNothing(), &pref_service_);
   absl::optional<BrowserDataMigrator::Result> result;
-  migrator->Migrate(base::BindLambdaForTesting(
-      [&out_result = result, &run_loop](BrowserDataMigrator::Result result) {
+  migrator->Migrate(
+      crosapi::browser_util::MigrationMode::kCopy,
+      base::BindLambdaForTesting([&out_result = result, &run_loop](
+                                     BrowserDataMigrator::Result result) {
         run_loop.Quit();
         out_result = result;
       }));
@@ -144,8 +146,10 @@
       std::make_unique<BrowserDataMigratorImpl>(
           from_dir_, user_id_hash, base::DoNothing(), &pref_service_);
   absl::optional<BrowserDataMigrator::Result> result;
-  migrator->Migrate(base::BindLambdaForTesting(
-      [&out_result = result, &run_loop](BrowserDataMigrator::Result result) {
+  migrator->Migrate(
+      crosapi::browser_util::MigrationMode::kCopy,
+      base::BindLambdaForTesting([&out_result = result, &run_loop](
+                                     BrowserDataMigrator::Result result) {
         run_loop.Quit();
         out_result = result;
       }));
@@ -192,8 +196,10 @@
       std::make_unique<BrowserDataMigratorImpl>(
           from_dir_, user_id_hash, base::DoNothing(), &pref_service_);
   absl::optional<BrowserDataMigrator::Result> result;
-  migrator->Migrate(base::BindLambdaForTesting(
-      [&out_result = result, &run_loop](BrowserDataMigrator::Result result) {
+  migrator->Migrate(
+      crosapi::browser_util::MigrationMode::kCopy,
+      base::BindLambdaForTesting([&out_result = result, &run_loop](
+                                     BrowserDataMigrator::Result result) {
         run_loop.Quit();
         out_result = result;
       }));
@@ -226,8 +232,10 @@
       std::make_unique<BrowserDataMigratorImpl>(
           from_dir_, user_id_hash, base::DoNothing(), &pref_service_);
   absl::optional<BrowserDataMigrator::Result> result;
-  migrator->Migrate(base::BindLambdaForTesting(
-      [&out_result = result, &run_loop](BrowserDataMigrator::Result result) {
+  migrator->Migrate(
+      crosapi::browser_util::MigrationMode::kMove,
+      base::BindLambdaForTesting([&out_result = result, &run_loop](
+                                     BrowserDataMigrator::Result result) {
         run_loop.Quit();
         out_result = result;
       }));
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h
index 5245f80..e0cc02b 100644
--- a/chrome/browser/ash/crosapi/browser_util.h
+++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -90,6 +90,13 @@
   const char* const crx_id;
 };
 
+// Specifies the mode of migration. The values correspond to `MigratorDelegate`
+// either being `CopyMigrator` or `MoveMigrator`.
+enum class MigrationMode {
+  kCopy = 0,  // Migrate using `CopyMigrator`.
+  kMove = 1,  // Migrate using `MoveMigrator`.
+};
+
 extern const ComponentInfo kLacrosDogfoodCanaryInfo;
 extern const ComponentInfo kLacrosDogfoodDevInfo;
 extern const ComponentInfo kLacrosDogfoodBetaInfo;
diff --git a/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc b/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc
index a04212d9f..5e7aa815 100644
--- a/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc
+++ b/chrome/browser/ash/login/screens/lacros_data_migration_screen.cc
@@ -115,7 +115,13 @@
         g_browser_process->local_state());
   }
 
-  migrator_->Migrate(base::BindOnce(&LacrosDataMigrationScreen::OnMigrated,
+  auto mode = base::CommandLine::ForCurrentProcess()->HasSwitch(
+                  switches::kBrowserDataMigrationMoveMode)
+                  ? crosapi::browser_util::MigrationMode::kMove
+                  : crosapi::browser_util::MigrationMode::kCopy;
+
+  migrator_->Migrate(mode,
+                     base::BindOnce(&LacrosDataMigrationScreen::OnMigrated,
                                     weak_factory_.GetWeakPtr()));
 
   // Show the screen.
diff --git a/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc b/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc
index 10a135216..d3e2ed85 100644
--- a/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc
+++ b/chrome/browser/ash/login/screens/lacros_data_migration_screen_browsertest.cc
@@ -43,7 +43,8 @@
 class FakeMigrator : public BrowserDataMigrator {
  public:
   // BrowserDataMigrator overrides.
-  void Migrate(MigrateCallback callback) override {
+  void Migrate(crosapi::browser_util::MigrationMode mode,
+               MigrateCallback callback) override {
     callback_ = std::move(callback);
   }
   void Cancel() override { cancel_called_ = true; }
diff --git a/chrome/browser/banners/android/BUILD.gn b/chrome/browser/banners/android/BUILD.gn
index d294746..6872a59 100644
--- a/chrome/browser/banners/android/BUILD.gn
+++ b/chrome/browser/banners/android/BUILD.gn
@@ -79,10 +79,10 @@
     "//third_party/android_deps:espresso_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit:junit",
     "//third_party/mockito:mockito_java",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_full_java",
     "//ui/android:ui_java_test_support",
   ]
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index d4d6018..cd5a626 100644
--- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -26,9 +26,6 @@
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
 import android.view.View;
 import android.widget.ImageView;
 import android.widget.TextView;
@@ -37,6 +34,9 @@
 import androidx.test.espresso.matcher.RootMatchers;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
 
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
diff --git a/chrome/browser/chromeos/extensions/default_app_order.cc b/chrome/browser/chromeos/extensions/default_app_order.cc
index 4c4769ba..d12b2b0 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order.cc
@@ -8,6 +8,7 @@
 
 #include "ash/constants/ash_paths.h"
 #include "ash/public/cpp/app_list/internal_app_id_constants.h"
+#include "ash/webui/projector_app/public/cpp/projector_app_constants.h"
 #include "base/bind.h"
 #include "base/callback_helpers.h"
 #include "base/files/file_path.h"
@@ -15,12 +16,14 @@
 #include "base/json/json_file_value_serializer.h"
 #include "base/path_service.h"
 #include "base/task/thread_pool.h"
+#include "chrome/browser/ash/crostini/crostini_terminal.h"
 #include "chrome/browser/ash/file_manager/app_id.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
 #include "chrome/browser/ui/app_list/page_break_constants.h"
 #include "chrome/browser/web_applications/web_app_id_constants.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/app_constants/constants.h"
 #include "extensions/common/constants.h"
 
@@ -38,8 +41,62 @@
 const char kNameAttr[] = "name";
 const char kImportDefaultOrderAttr[] = "import_default_order";
 
-// Canonical ordering specified in: go/default-apps
-const char* const kDefaultAppOrder[] = {
+// Reads external ordinal json file and returned the parsed value. Returns NULL
+// if the file does not exist or could not be parsed properly. Caller takes
+// ownership of the returned value.
+std::unique_ptr<base::ListValue> ReadExternalOrdinalFile(
+    const base::FilePath& path) {
+  if (!base::PathExists(path))
+    return NULL;
+
+  JSONFileValueDeserializer deserializer(path);
+  std::string error_msg;
+  std::unique_ptr<base::Value> value =
+      deserializer.Deserialize(NULL, &error_msg);
+  if (!value) {
+    LOG(WARNING) << "Unable to deserialize default app ordinals json data:"
+                 << error_msg << ", file=" << path.value();
+    return NULL;
+  }
+
+  std::unique_ptr<base::ListValue> ordinal_list_value =
+      base::ListValue::From(std::move(value));
+  if (!ordinal_list_value)
+    LOG(WARNING) << "Expect a JSON list in file " << path.value();
+
+  return ordinal_list_value;
+}
+
+std::string GetLocaleSpecificStringImpl(const base::DictionaryValue* root,
+                                        const std::string& locale,
+                                        const std::string& dictionary_name,
+                                        const std::string& entry_name) {
+  const base::DictionaryValue* dictionary_content = NULL;
+  if (!root || !root->GetDictionary(dictionary_name, &dictionary_content))
+    return std::string();
+
+  const base::DictionaryValue* locale_dictionary = NULL;
+  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
+    std::string result;
+    if (locale_dictionary->GetString(entry_name, &result))
+      return result;
+  }
+
+  const base::DictionaryValue* default_dictionary = NULL;
+  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
+    std::string result;
+    if (default_dictionary->GetString(entry_name, &result))
+      return result;
+  }
+
+  return std::string();
+}
+
+// Gets built-in default app order.
+void GetDefault(std::vector<std::string>* app_ids) {
+  // Canonical ordering specified in: go/default-apps
+  // clang-format off
+  app_ids->insert(app_ids->end(), {
     app_constants::kChromeAppId,
     arc::kPlayStoreAppId,
 
@@ -85,6 +142,7 @@
 
     arc::kPlayMoviesAppId,
     extension_misc::kGooglePlayMoviesAppId,
+    arc::kGoogleTVAppId,
 
     arc::kPlayMusicAppId,
     extension_misc::kGooglePlayMusicAppId,
@@ -98,14 +156,12 @@
     arc::kGooglePhotosAppId,
     extension_misc::kGooglePhotosAppId,
 
-    arc::kGoogleDuoAppId,
     web_app::kStadiaAppId,
 
     // First default page break
     app_list::kDefaultPageBreak1,
 
     arc::kGoogleMapsAppId,
-    extension_misc::kGoogleMapsAppId,  // TODO(crbug.com/976578): Remove.
     web_app::kGoogleMapsAppId,
 
     ash::kInternalAppIdSettings,
@@ -123,73 +179,32 @@
     web_app::kYoutubeTVAppId,
     web_app::kGoogleNewsAppId,
     extensions::kWebStoreAppId,
+
+    crostini::kCrostiniTerminalSystemAppId,
+    web_app::kMediaAppId,
+    ash::kChromeUITrustedProjectorSwaAppId,
+
     arc::kLightRoomAppId,
     arc::kInfinitePainterAppId,
     web_app::kShowtimeAppId,
     extension_misc::kGooglePlusAppId,
-};
+  });
+  // clang-format on
 
-// Reads external ordinal json file and returned the parsed value. Returns NULL
-// if the file does not exist or could not be parsed properly. Caller takes
-// ownership of the returned value.
-std::unique_ptr<base::ListValue> ReadExternalOrdinalFile(
-    const base::FilePath& path) {
-  if (!base::PathExists(path))
-    return NULL;
-
-  JSONFileValueDeserializer deserializer(path);
-  std::string error_msg;
-  std::unique_ptr<base::Value> value =
-      deserializer.Deserialize(NULL, &error_msg);
-  if (!value) {
-    LOG(WARNING) << "Unable to deserialize default app ordinals json data:"
-        << error_msg << ", file=" << path.value();
-    return NULL;
+  if (chromeos::features::IsCloudGamingDeviceEnabled()) {
+    app_ids->push_back(web_app::kCloudGamingPartnerPlatform);
   }
-
-  std::unique_ptr<base::ListValue> ordinal_list_value =
-      base::ListValue::From(std::move(value));
-  if (!ordinal_list_value)
-    LOG(WARNING) << "Expect a JSON list in file " << path.value();
-
-  return ordinal_list_value;
-}
-
-std::string GetLocaleSpecificStringImpl(
-    const base::DictionaryValue* root,
-    const std::string& locale,
-    const std::string& dictionary_name,
-    const std::string& entry_name) {
-  const base::DictionaryValue* dictionary_content = NULL;
-  if (!root || !root->GetDictionary(dictionary_name, &dictionary_content))
-    return std::string();
-
-  const base::DictionaryValue* locale_dictionary = NULL;
-  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
-    std::string result;
-    if (locale_dictionary->GetString(entry_name, &result))
-      return result;
-  }
-
-  const base::DictionaryValue* default_dictionary = NULL;
-  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
-    std::string result;
-    if (default_dictionary->GetString(entry_name, &result))
-      return result;
-  }
-
-  return std::string();
-}
-
-// Gets built-in default app order.
-void GetDefault(std::vector<std::string>* app_ids) {
-  for (size_t i = 0; i < std::size(kDefaultAppOrder); ++i)
-    app_ids->push_back(std::string(kDefaultAppOrder[i]));
 }
 
 }  // namespace
 
-const size_t kDefaultAppOrderCount = std::size(kDefaultAppOrder);
+size_t DefaultAppCount() {
+  std::vector<std::string> apps;
+
+  GetDefault(&apps);
+
+  return apps.size();
+}
 
 ExternalLoader::ExternalLoader(bool async)
     : loaded_(base::WaitableEvent::ResetPolicy::MANUAL,
diff --git a/chrome/browser/chromeos/extensions/default_app_order.h b/chrome/browser/chromeos/extensions/default_app_order.h
index 495d11c..546a09b 100644
--- a/chrome/browser/chromeos/extensions/default_app_order.h
+++ b/chrome/browser/chromeos/extensions/default_app_order.h
@@ -52,7 +52,7 @@
 std::string GetOemAppsFolderName();
 
 // Number of apps in hard-coded apps order.
-extern const size_t kDefaultAppOrderCount;
+size_t DefaultAppCount();
 
 }  // namespace default_app_order
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
index 34fe98a..f8d2f1c0 100644
--- a/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
+++ b/chrome/browser/chromeos/extensions/default_app_order_unittest.cc
@@ -139,11 +139,11 @@
 
   std::vector<std::string> apps;
   default_app_order::Get(&apps);
-  EXPECT_EQ(default_app_order::kDefaultAppOrderCount + 2, apps.size());
+  EXPECT_EQ(default_app_order::DefaultAppCount() + 2, apps.size());
   EXPECT_EQ(std::string("app1"), apps[0]);
   EXPECT_EQ(app_constants::kChromeAppId, apps[1]);
   EXPECT_EQ(std::string("app2"),
-            apps[default_app_order::kDefaultAppOrderCount + 1]);
+            apps[default_app_order::DefaultAppCount() + 1]);
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
index 29a9f9f5a..bd1fdff6 100644
--- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
+++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.cc
@@ -191,26 +191,31 @@
   Respond(NoArguments());
 }
 
-WmDesksPrivateLaunchDeskTemplateFunction::
-    WmDesksPrivateLaunchDeskTemplateFunction() = default;
-WmDesksPrivateLaunchDeskTemplateFunction::
-    ~WmDesksPrivateLaunchDeskTemplateFunction() = default;
+WmDesksPrivateLaunchDeskFunction::WmDesksPrivateLaunchDeskFunction() = default;
+WmDesksPrivateLaunchDeskFunction::~WmDesksPrivateLaunchDeskFunction() = default;
 
-ExtensionFunction::ResponseAction
-WmDesksPrivateLaunchDeskTemplateFunction::Run() {
-  std::unique_ptr<api::wm_desks_private::LaunchDeskTemplate::Params> params(
-      api::wm_desks_private::LaunchDeskTemplate::Params::Create(args()));
+ExtensionFunction::ResponseAction WmDesksPrivateLaunchDeskFunction::Run() {
+  std::unique_ptr<api::wm_desks_private::LaunchDesk::Params> params(
+      api::wm_desks_private::LaunchDesk::Params::Create(args()));
   EXTENSION_FUNCTION_VALIDATE(params);
-
-  DesksClient::Get()->LaunchDeskTemplate(
-      params->template_uuid,
-      base::BindOnce(
-          &WmDesksPrivateLaunchDeskTemplateFunction::OnLaunchDeskTemplate,
-          this));
-  return RespondLater();
+  auto& launch_options = params->launch_options;
+  std::u16string desk_name = launch_options.desk_name
+                                 ? base::UTF8ToUTF16(*launch_options.desk_name)
+                                 : u"";
+  if (launch_options.template_uuid) {
+    DesksClient::Get()->LaunchDeskTemplate(
+        *params->launch_options.template_uuid,
+        base::BindOnce(&WmDesksPrivateLaunchDeskFunction::OnLaunchDesk, this),
+        desk_name);
+  } else {
+    DesksClient::Get()->LaunchEmptyDesk(
+        base::BindOnce(&WmDesksPrivateLaunchDeskFunction::OnLaunchDesk, this),
+        desk_name);
+  }
+  return did_respond() ? AlreadyResponded() : RespondLater();
 }
 
-void WmDesksPrivateLaunchDeskTemplateFunction::OnLaunchDeskTemplate(
+void WmDesksPrivateLaunchDeskFunction::OnLaunchDesk(
     std::string error_string,
     const base::GUID& desk_uuid) {
   if (!error_string.empty()) {
@@ -218,9 +223,8 @@
     return;
   }
 
-  Respond(
-      ArgumentList(api::wm_desks_private::LaunchDeskTemplate::Results::Create(
-          desk_uuid.AsLowercaseString())));
+  Respond(ArgumentList(api::wm_desks_private::LaunchDesk::Results::Create(
+      desk_uuid.AsLowercaseString())));
 }
 
 WmDesksPrivateRemoveDeskFunction::WmDesksPrivateRemoveDeskFunction() = default;
diff --git a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h
index ff99e058..be00f4bccd 100644
--- a/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h
+++ b/chrome/browser/chromeos/extensions/wm/wm_desks_private_api.h
@@ -122,25 +122,24 @@
   void OnDeleteDeskTemplateCompleted(std::string error_string);
 };
 
-class WmDesksPrivateLaunchDeskTemplateFunction : public ExtensionFunction {
+class WmDesksPrivateLaunchDeskFunction : public ExtensionFunction {
  public:
-  WmDesksPrivateLaunchDeskTemplateFunction();
-  WmDesksPrivateLaunchDeskTemplateFunction(
-      const WmDesksPrivateLaunchDeskTemplateFunction&) = delete;
-  WmDesksPrivateLaunchDeskTemplateFunction& operator=(
-      const WmDesksPrivateLaunchDeskTemplateFunction&) = delete;
+  WmDesksPrivateLaunchDeskFunction();
+  WmDesksPrivateLaunchDeskFunction(const WmDesksPrivateLaunchDeskFunction&) =
+      delete;
+  WmDesksPrivateLaunchDeskFunction& operator=(
+      const WmDesksPrivateLaunchDeskFunction&) = delete;
 
-  DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.launchDeskTemplate",
-                             WMDESKSPRIVATE_LAUNCHDESKTEMPLATE)
+  DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.launchDesk",
+                             WMDESKSPRIVATE_LAUNCHDESK)
 
  protected:
-  ~WmDesksPrivateLaunchDeskTemplateFunction() override;
+  ~WmDesksPrivateLaunchDeskFunction() override;
 
   // ExtensionFunction:
   ResponseAction Run() override;
 
-  void OnLaunchDeskTemplate(std::string error_string,
-                            const base::GUID& desk_Id);
+  void OnLaunchDesk(std::string error_string, const base::GUID& desk_Id);
 };
 
 class WmDesksPrivateRemoveDeskFunction : public ExtensionFunction {
@@ -151,8 +150,8 @@
   WmDesksPrivateRemoveDeskFunction& operator=(
       const WmDesksPrivateRemoveDeskFunction&) = delete;
 
-  DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.removeDeskAndCloseWindows",
-                             WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS)
+  DECLARE_EXTENSION_FUNCTION("wmDesksPrivate.removeDesk",
+                             WMDESKSPRIVATE_REMOVEDESK)
  protected:
   ~WmDesksPrivateRemoveDeskFunction() override;
 
diff --git a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc
index a9028740..4e1b9c6 100644
--- a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc
+++ b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.cc
@@ -2,8 +2,30 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// Lacros specific FileBrowserHandlerInternalSelectFileFunctionLacros overrides
+// OnFilePathSelected() to do the following:
+// * Use storage::IsolatedContext to create extensions::GrantedFileEntry.
+// * Grant permissions needed to read/write/create file under the select path.
+// * Populate results for API response needed to create JS FileEntry.
+
 #include "chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h"
-#include "base/notreached.h"
+
+#include <memory>
+#include <utility>
+
+#include "chrome/common/extensions/api/file_browser_handler_internal.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "extensions/browser/api/file_handlers/app_file_handler_util.h"
+#include "extensions/browser/granted_file_entry.h"
+
+using content::BrowserThread;
+using extensions::api::file_browser_handler_internal::FileEntryInfoForGetFile;
+using extensions::app_file_handler_util::CreateFileEntryWithPermissions;
+
+namespace SelectFile =
+    extensions::api::file_browser_handler_internal::SelectFile;
 
 FileBrowserHandlerInternalSelectFileFunctionLacros::
     FileBrowserHandlerInternalSelectFileFunctionLacros() = default;
@@ -14,16 +36,35 @@
 void FileBrowserHandlerInternalSelectFileFunctionLacros::OnFilePathSelected(
     bool success,
     const base::FilePath& full_path) {
-  // Called by FileBrowserHandlerInternalSelectFileFunction::Run(), which is
-  // stubbed out.
-  NOTREACHED();
-}
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-ExtensionFunction::ResponseAction
-FileBrowserHandlerInternalSelectFileFunctionLacros::Run() {
-  NOTIMPLEMENTED();
-  return RespondNow(
-      Error("fileBrowserHandlerInternal.selectFile not implemented"));
+  if (!success) {
+    RespondWithFailure();
+    return;
+  }
+
+  int renderer_pid = render_frame_host()->GetProcess()->GetID();
+  if (renderer_pid <= 0) {
+    RespondWithFailure();
+    return;
+  }
+
+  extensions::GrantedFileEntry granted_file_entry =
+      CreateFileEntryWithPermissions(
+          renderer_pid, full_path,
+          /* can_write */ true, /* can_create */ true, /* can_delete */ false);
+
+  SelectFile::Results::Result result;
+  result.success = true;
+
+  // The value will be consumed by DirectoryEntry.getFile() (JS).
+  result.entry_for_get_file = std::make_unique<FileEntryInfoForGetFile>();
+  result.entry_for_get_file->file_system_id = granted_file_entry.filesystem_id;
+  result.entry_for_get_file->base_name = granted_file_entry.registered_name;
+  result.entry_for_get_file->entry_id = granted_file_entry.id;
+  result.entry_for_get_file->is_directory = false;
+
+  RespondWithResult(result);
 }
 
 template <>
diff --git a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h
index 5a1ec2b..69a08902 100644
--- a/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h
+++ b/chrome/browser/extensions/api/file_manager/file_browser_handler_api_lacros.h
@@ -24,10 +24,6 @@
   // The class is ref counted, so destructor should not be public.
   ~FileBrowserHandlerInternalSelectFileFunctionLacros() override;
 
-  // ExtensionFunction implementation.
-  // Runs the extension function implementation.
-  ResponseAction Run() override;
-
  private:
   DECLARE_EXTENSION_FUNCTION("fileBrowserHandlerInternal.selectFile",
                              FILEBROWSERHANDLERINTERNAL_SELECTFILE)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 6af50d14..28ca3371 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1982,6 +1982,11 @@
     "expiry_milestone": 106
   },
   {
+    "name": "enable-discover-feed-ghost-cards",
+    "owners": [ "edchin", "adamta", "sczs", "tinazwang" ],
+    "expiry_milestone": 106
+  },
+  {
     "name": "enable-discover-feed-preview",
     "owners": [ "tinazwang", "sczs" ],
     "expiry_milestone": 101
@@ -4301,6 +4306,11 @@
     "expiry_milestone": 93
   },
   {
+    "name": "new-instance-from-dragged-link",
+    "owners": [ "aishwaryarj", "clank-app-team@google.com" ],
+    "expiry_milestone": 106
+  },
+  {
     "name": "new-mobile-identity-consistency-fre",
     "owners": [ "jlebel", "chrome-signin-team" ],
     "expiry_milestone": 106
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index d9e4c49..76f58d1 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3411,6 +3411,11 @@
     "When enabled, the network service runs on the browser process. Otherwise, "
     "it runs on a dedicated process.";
 
+const char kNewInstanceFromDraggedLinkName[] =
+    "New instance creation from a dragged link";
+const char kNewInstanceFromDraggedLinkDescription[] =
+    "Enables creation of a new instance when a link is dragged out of Chrome.";
+
 const char kNewWindowAppMenuName[] = "Show a menu item 'New Window'";
 const char kNewWindowAppMenuDescription[] =
     "Show a new menu item 'New Window' on tablet-sized screen when Chrome "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index e91a9f5..144f98e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1941,6 +1941,9 @@
 extern const char kNetworkServiceInProcessName[];
 extern const char kNetworkServiceInProcessDescription[];
 
+extern const char kNewInstanceFromDraggedLinkName[];
+extern const char kNewInstanceFromDraggedLinkDescription[];
+
 extern const char kNewWindowAppMenuName[];
 extern const char kNewWindowAppMenuDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 3703c78e..db566f0 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -190,6 +190,7 @@
     &kCCTResizableAllowResizeByUserGesture,
     &kCCTResizableForFirstParties,
     &kCCTResizableForThirdParties,
+    &kCCTRetainingState,
     &kCCTResourcePrefetch,
     &kCCTToolbarCustomizations,
     &kDontAutoHideBrowserControls,
@@ -244,6 +245,7 @@
     &kLensOnQuickActionSearchWidget,
     &kLocationBarModelOptimizations,
     &kMostRecentTabOnBackgroundCloseTab,
+    &kNewInstanceFromDraggedLink,
     &kNewWindowAppMenu,
     &kNotificationPermissionVariant,
     &kPageAnnotationsService,
@@ -364,6 +366,7 @@
     &query_tiles::features::kQueryTilesSegmentation,
     &reading_list::switches::kReadLater,
     &safe_browsing::kCreateSafebrowsingOnStartup,
+    &segmentation_platform::features::kContextualPageActions,
     &segmentation_platform::features::kContextualPageActionPriceTracking,
     &send_tab_to_self::kSendTabToSelfSigninPromo,
     &send_tab_to_self::kSendTabToSelfV2,
@@ -492,6 +495,9 @@
 const base::Feature kCCTIncognitoAvailableToThirdParty{
     "CCTIncognitoAvailableToThirdParty", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kCCTPackageNameRecording{"CCTPackageNameRecording",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kCCTPostMessageAPI{"CCTPostMessageAPI",
                                        base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -519,6 +525,9 @@
 const base::Feature kCCTResourcePrefetch{"CCTResourcePrefetch",
                                          base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kCCTRetainingState{"CCTRetainingState",
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kCCTToolbarCustomizations{"CCTToolbarCustomizations",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -687,6 +696,9 @@
 const base::Feature kMostRecentTabOnBackgroundCloseTab{
     "MostRecentTabOnBackgroundCloseTab", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kNewInstanceFromDraggedLink{
+    "NewInstanceFromDraggedLink", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kNewWindowAppMenu{"NewWindowAppMenu",
                                       base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 7ad04adb..2fafc23 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -38,6 +38,7 @@
 extern const base::Feature kCCTIncognito;
 extern const base::Feature kCCTIncognitoAvailableToThirdParty;
 extern const base::Feature kCCTNewDownloadTab;
+extern const base::Feature kCCTPackageNameRecording;
 extern const base::Feature kCCTPostMessageAPI;
 extern const base::Feature kCCTRedirectPreconnect;
 extern const base::Feature kCCTRemoveRemoteViewIds;
@@ -47,6 +48,7 @@
 extern const base::Feature kCCTResizableForFirstParties;
 extern const base::Feature kCCTResizableForThirdParties;
 extern const base::Feature kCCTResourcePrefetch;
+extern const base::Feature kCCTRetainingState;
 extern const base::Feature kCCTToolbarCustomizations;
 extern const base::Feature kDontAutoHideBrowserControls;
 extern const base::Feature kChromeNewDownloadTab;
@@ -106,6 +108,7 @@
 extern const base::Feature kLensOnQuickActionSearchWidget;
 extern const base::Feature kLocationBarModelOptimizations;
 extern const base::Feature kMostRecentTabOnBackgroundCloseTab;
+extern const base::Feature kNewInstanceFromDraggedLink;
 extern const base::Feature kNewWindowAppMenu;
 extern const base::Feature kNotificationPermissionVariant;
 extern const base::Feature kPageAnnotationsService;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index df02578..be7eb27d 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -256,6 +256,7 @@
     public static final String CCT_RESIZABLE_FOR_FIRST_PARTIES = "CCTResizableForFirstParties";
     public static final String CCT_RESIZABLE_FOR_THIRD_PARTIES = "CCTResizableForThirdParties";
     public static final String CCT_RESOURCE_PREFETCH = "CCTResourcePrefetch";
+    public static final String CCT_RETAINING_STATE = "CCTRetainingState";
     public static final String CCT_REPORT_PARALLEL_REQUEST_STATUS =
             "CCTReportParallelRequestStatus";
     public static final String CCT_TOOLBAR_CUSTOMIZATIONS = "CCTToolbarCustomizations";
@@ -414,6 +415,7 @@
     public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid";
     public static final String MOST_RECENT_TAB_ON_BACKGROUND_CLOSE_TAB =
             "MostRecentTabOnBackgroundCloseTab";
+    public static final String NEW_INSTANCE_FROM_DRAGGED_LINK = "NewInstanceFromDraggedLink";
     public static final String NEW_WINDOW_APP_MENU = "NewWindowAppMenu";
     public static final String NOTIFICATION_PERMISSION_VARIANT = "NotificationPermissionVariant";
     public static final String OFFLINE_INDICATOR = "OfflineIndicator";
diff --git a/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml b/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml
index 01375bb..a166077 100644
--- a/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml
+++ b/chrome/browser/history_clusters/java/res/menu/history_clusters_menu.xml
@@ -13,6 +13,12 @@
         android:visible="false"
         app:showAsAction="ifRoom"
         app:iconTint="@color/default_icon_color_secondary_tint_list" />
+    <item
+        android:id="@+id/close_menu_id"
+        android:icon="@drawable/btn_close"
+        android:title="@string/close"
+        app:showAsAction="ifRoom"
+        app:iconTint="@color/default_icon_color_secondary_tint_list" />
   </group>
   <group
       android:id="@+id/selection_mode_menu_group"
diff --git a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java
index 8a50ffa..12af94bd 100644
--- a/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java
+++ b/chrome/browser/history_clusters/java/src/org/chromium/chrome/browser/history_clusters/HistoryClustersCoordinator.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.browser.history_clusters;
 
-import android.content.Context;
+import android.app.Activity;
 import android.view.LayoutInflater;
 import android.view.MenuItem;
 import android.view.View;
@@ -36,7 +36,7 @@
     private final ModelList mModelList;
     private final HistoryClustersDelegate mDelegate;
     private SimpleRecyclerViewAdapter mAdapter;
-    private final Context mContext;
+    private final Activity mActivity;
     private boolean mActivityViewInflated;
     private final PropertyModel mToolbarModel;
     private ViewGroup mActivityContentView;
@@ -47,15 +47,14 @@
     /**
      * Construct a new HistoryClustersCoordinator.
      * @param profile The profile from which the coordinator should access history data.
-     * @param context Android context from which UI configuration (strings, colors etc.) should be
-     *         derived.
+     * @param activity Activity in which this UI resides.
      * @param historyClustersDelegate Delegate that provides functionality that must be implemented
      *         externally, e.g. populating intents targeting activities we can't reference directly.
      */
-    public HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Context context,
+    public HistoryClustersCoordinator(@NonNull Profile profile, @NonNull Activity activity,
             TemplateUrlService templateUrlService,
             HistoryClustersDelegate historyClustersDelegate) {
-        mContext = context;
+        mActivity = activity;
         mDelegate = historyClustersDelegate;
         mModelList = new ModelList();
         mToolbarModel = new PropertyModel.Builder(HistoryClustersToolbarProperties.ALL_KEYS)
@@ -63,7 +62,7 @@
                                         QueryState.forQueryless())
                                 .build();
         mMediator = new HistoryClustersMediator(HistoryClustersBridge.getForProfile(profile),
-                new LargeIconBridge(profile), context, context.getResources(), mModelList,
+                new LargeIconBridge(profile), mActivity, mActivity.getResources(), mModelList,
                 mToolbarModel, mDelegate, System::currentTimeMillis, templateUrlService);
     }
 
@@ -107,7 +106,7 @@
         mAdapter.registerType(ItemType.TOGGLE, mDelegate::getToggleView,
                 HistoryClustersViewBinder::bindToggleView);
 
-        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
+        LayoutInflater layoutInflater = LayoutInflater.from(mActivity);
         mActivityContentView = (ViewGroup) layoutInflater.inflate(
                 R.layout.history_clusters_activity_content, null);
 
@@ -129,6 +128,9 @@
                 mMediator, R.string.history_clusters_search_your_journeys, R.id.search_menu_id);
         mSelectableListLayout.configureWideDisplayStyle();
         mToolbar.setSearchEnabled(true);
+        if (!mDelegate.isSeparateActivity()) {
+            mToolbar.getMenu().removeItem(R.id.close_menu_id);
+        }
 
         PropertyModelChangeProcessor.create(
                 mToolbarModel, mToolbar, HistoryClustersViewBinder::bindToolbar);
@@ -163,6 +165,10 @@
             mMediator.setQueryState(QueryState.forQuery(""));
             return true;
         }
+        if (menuItem.getItemId() == R.id.close_menu_id && mDelegate.isSeparateActivity()) {
+            mActivity.finish();
+            return true;
+        }
         return false;
     }
 }
\ No newline at end of file
diff --git a/chrome/browser/metrics/chrome_android_metrics_provider.cc b/chrome/browser/metrics/chrome_android_metrics_provider.cc
index af0c834f..1658ca67 100644
--- a/chrome/browser/metrics/chrome_android_metrics_provider.cc
+++ b/chrome/browser/metrics/chrome_android_metrics_provider.cc
@@ -6,8 +6,10 @@
 
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
+#include "chrome/browser/android/customtabs/custom_tab_session_state_tracker.h"
 #include "chrome/browser/android/locale/locale_manager.h"
 #include "chrome/browser/android/metrics/uma_session_stats.h"
+#include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "chrome/browser/flags/android/chrome_session_state.h"
 #include "chrome/browser/notifications/jni_headers/NotificationSystemStatusUtil_jni.h"
 #include "components/prefs/pref_registry_simple.h"
@@ -93,6 +95,15 @@
   os_proto->set_dark_mode_state(
       ToProtoDarkModeState(chrome::android::GetDarkModeState()));
 
+  if (base::FeatureList::IsEnabled(chrome::android::kCCTPackageNameRecording) &&
+      chrome::android::CustomTabSessionStateTracker::GetInstance()
+          .HasCustomTabSessionState()) {
+    uma_proto->mutable_custom_tab_session()->Swap(
+        chrome::android::CustomTabSessionStateTracker::GetInstance()
+            .GetSession()
+            .get());
+  }
+
   UmaSessionStats::GetInstance()->ProvideCurrentSessionData();
   EmitAppNotificationStatusHistogram();
   LocaleManager::RecordUserTypeMetrics();
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
index e08a1d1..6348af1 100644
--- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
+++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -238,7 +238,7 @@
   const char* kScenarioSuffix = ".VideoCapture";
   const std::vector<const char*> suffixes({"", kScenarioSuffix});
   ExpectHistogramSamples(&histogram_tester_, suffixes,
-                         {{"PerformanceMonitor.AverageCPU4.Total", 500}});
+                         {{"PerformanceMonitor.AverageCPU5.Total", 500}});
 }
 
 #if BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/metrics/power/power_metrics_unittest.cc b/chrome/browser/metrics/power/power_metrics_unittest.cc
index d7aec2a..505cd02 100644
--- a/chrome/browser/metrics/power/power_metrics_unittest.cc
+++ b/chrome/browser/metrics/power/power_metrics_unittest.cc
@@ -84,7 +84,7 @@
   ReportAggregatedProcessMetricsHistograms(process_metrics, suffixes);
 
   ExpectHistogramSamples(&histogram_tester, suffixes, {
-    {"PerformanceMonitor.AverageCPU4.Total", 20},
+    {"PerformanceMonitor.AverageCPU5.Total", 20},
 
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
     BUILDFLAG(IS_AIX)
diff --git a/chrome/browser/metrics/power/process_metrics_recorder_util.cc b/chrome/browser/metrics/power/process_metrics_recorder_util.cc
index ca6df4d..56a4542a 100644
--- a/chrome/browser/metrics/power/process_metrics_recorder_util.cc
+++ b/chrome/browser/metrics/power/process_metrics_recorder_util.cc
@@ -26,14 +26,38 @@
 constexpr int kCPUUsageHistogramMax = 200 * kCPUUsageFactor;
 constexpr int kCPUUsageHistogramBucketCount = 50;
 
+#if BUILDFLAG(IS_WIN)
+bool HasConstantRateTSC() {
+#if defined(ARCH_CPU_ARM64)
+  // Constant rate TSC is never support on Arm CPUs.
+  return false;
+#else
+  // Probe the CPU to detect if constant-rate TSC is supported.
+  return base::time_internal::HasConstantRateTSC();
+#endif
+}
+#endif  // BUILDFLAG(IS_WIN)
+
+void RecordAverageCPUUsage(const char* histogram_suffix, double cpu_usage) {
+#if BUILDFLAG(IS_WIN)
+  // Skip recording the average CPU usage if the CPU doesn't support constant
+  // rate TSC, since Windows does not offer a way to get a precise measurement
+  // without it.
+  if (!HasConstantRateTSC())
+    return;
+#endif
+
+  base::UmaHistogramCustomCounts(
+      base::StrCat({"PerformanceMonitor.AverageCPU5.", histogram_suffix}),
+      cpu_usage * kCPUUsageFactor, kCPUUsageHistogramMin, kCPUUsageHistogramMax,
+      kCPUUsageHistogramBucketCount);
+}
+
 }  // namespace
 
 void RecordProcessHistograms(const char* histogram_suffix,
                              const ProcessMonitor::Metrics& metrics) {
-  base::UmaHistogramCustomCounts(
-      base::StrCat({"PerformanceMonitor.AverageCPU4.", histogram_suffix}),
-      metrics.cpu_usage * kCPUUsageFactor, kCPUUsageHistogramMin,
-      kCPUUsageHistogramMax, kCPUUsageHistogramBucketCount);
+  RecordAverageCPUUsage(histogram_suffix, metrics.cpu_usage);
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
     BUILDFLAG(IS_AIX)
   base::UmaHistogramCounts10000(
diff --git a/chrome/browser/metrics/power/process_monitor.cc b/chrome/browser/metrics/power/process_monitor.cc
index 0a1ebbb0..1dfa63ac 100644
--- a/chrome/browser/metrics/power/process_monitor.cc
+++ b/chrome/browser/metrics/power/process_monitor.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/observer_list.h"
 #include "base/process/process_handle.h"
 #include "base/process/process_metrics.h"
@@ -151,6 +152,13 @@
   // Do an initial call to SampleMetrics() so that the next one returns
   // meaningful data.
   SampleMetrics(*this->process_metrics);
+
+#if BUILDFLAG(IS_WIN) && !defined(ARCH_CPU_ARM64)
+  // Record the value of HasConstantRateTSC to get a feel of the proportion of
+  // users that don't record the average CPU usage histogram.
+  base::UmaHistogramBoolean("PerformanceMonitor.HasPreciseCPUUsage",
+                            base::time_internal::HasConstantRateTSC());
+#endif
 }
 ProcessInfo::~ProcessInfo() = default;
 
diff --git a/chrome/browser/paint_preview/android/BUILD.gn b/chrome/browser/paint_preview/android/BUILD.gn
index 1231141..7202ca8f 100644
--- a/chrome/browser/paint_preview/android/BUILD.gn
+++ b/chrome/browser/paint_preview/android/BUILD.gn
@@ -85,9 +85,9 @@
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/junit",
     "//third_party/mockito:mockito_java",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java_test_support",
     "//ui/android:ui_no_recycler_view_java",
     "//url:gurl_java",
diff --git a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java
index 84e1cc0..cdf85318 100644
--- a/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java
+++ b/chrome/browser/paint_preview/android/javatests/src/org/chromium/chrome/browser/paint_preview/DemoPaintPreviewTest.java
@@ -7,9 +7,8 @@
 import static org.chromium.base.test.util.Batch.PER_CLASS;
 import static org.chromium.chrome.browser.paint_preview.TabbedPaintPreviewTest.assertAttachedAndShown;
 
-import android.support.test.uiautomator.UiObjectNotFoundException;
-
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.UiObjectNotFoundException;
 
 import org.junit.AfterClass;
 import org.junit.Assert;
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
index f5a54bcd..4c8cf99e 100644
--- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
+++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -209,6 +209,10 @@
     public static final KeyPrefix CUSTOM_TABS_DEX_LAST_UPDATE_TIME_PREF_PREFIX =
             new KeyPrefix("pref_local_custom_tabs_module_dex_last_update_time_*");
     public static final String CUSTOM_TABS_LAST_URL = "pref_last_custom_tab_url";
+    public static final String CUSTOM_TABS_LAST_CLOSE_TIMESTAMP =
+            "Chrome.CustomTabs.LastCloseTimestamp";
+    public static final String CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION =
+            "Chrome.CustomTabs.LastCloseTabInteraction";
 
     /**
      * Keys used to save whether it is ready to promo.
@@ -966,6 +970,8 @@
                 CONTEXT_MENU_SHOP_IMAGE_WITH_GOOGLE_LENS_CLICKED,
                 CONTINUOUS_SEARCH_DISMISSAL_COUNT,
                 CRYPTID_LAST_RENDER_TIMESTAMP,
+                CUSTOM_TABS_LAST_CLOSE_TIMESTAMP,
+                CUSTOM_TABS_LAST_CLOSE_TAB_INTERACTION,
                 DEFAULT_BROWSER_PROMO_LAST_DEFAULT_STATE,
                 DEFAULT_BROWSER_PROMO_LAST_PROMO_TIME,
                 DEFAULT_BROWSER_PROMO_PROMOED_BY_SYSTEM_SETTINGS,
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index ef28a9d..e4daa3d3 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -253,7 +253,6 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/clipboard_history_controller.h"
-#include "ash/public/cpp/new_window_delegate.h"
 #include "chrome/browser/ash/arc/arc_util.h"
 #include "chrome/browser/ash/arc/intent_helper/arc_intent_helper_mojo_ash.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_rules_manager.h"
@@ -2765,16 +2764,10 @@
 
     case IDC_CONTENT_CONTEXT_SEARCHWEBFOR:
     case IDC_CONTENT_CONTEXT_GOTOURL:
-#if BUILDFLAG(IS_CHROMEOS_ASH)
-      ash::NewWindowDelegate::GetPrimary()->OpenUrl(
-          selection_navigation_url_,
-          ash::NewWindowDelegate::OpenUrlFrom::kUserInteraction);
-#else
       OpenURL(selection_navigation_url_, GURL(),
               ui::DispositionFromEventFlags(
                   event_flags, WindowOpenDisposition::NEW_FOREGROUND_TAB),
               ui::PAGE_TRANSITION_LINK);
-#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
       break;
 
     case IDC_CONTENT_CONTEXT_LANGUAGE_SETTINGS:
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
index 6219eeb..b4ba693 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/BUILD.gn
@@ -51,6 +51,7 @@
     "dictation/macros/macro.js",
     "dictation/macros/macro_names.js",
     "dictation/macros/repeatable_key_press_macro.js",
+    "dictation/macros/smart_delete_phrase_macro.js",
     "dictation/macros/stop_listening_macro.js",
     "dictation/metrics_utils.js",
     "dictation/parse/input_text_strategy.js",
@@ -240,6 +241,7 @@
     "dictation/macros/macro.js",
     "dictation/macros/macro_names.js",
     "dictation/macros/repeatable_key_press_macro.js",
+    "dictation/macros/smart_delete_phrase_macro.js",
     "dictation/macros/stop_listening_macro.js",
   ]
   deps = [
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js
index ef92840..e5e511a 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/dictation.js
@@ -477,6 +477,14 @@
   runHiddenMacroForTesting(name) {
     this.hiddenMacroManager_.runMacroForTesting(name);
   }
+
+  /**
+   * @param {!MacroName} Name The macro to run.
+   * @param {string} arg
+   */
+  runHiddenMacroWithStringArgForTesting(name, arg) {
+    this.hiddenMacroManager_.runMacroWithStringArgForTesting(name, arg);
+  }
 }
 
 /**
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js
index 2e90a38..37de5bcf 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/input_controller.js
@@ -227,6 +227,45 @@
       offset
     });
   }
+
+  /**
+   * Deletes a phrase to the left of the text caret. If multiple instances of
+   * `phrase` are present, it deletes the one closest to the text caret.
+   * @param {string} phrase The phrase to be deleted.
+   */
+  smartDeletePhrase(phrase) {
+    const editableNode = this.focusHandler_.getEditableNode();
+    if (!editableNode || !editableNode.value ||
+        editableNode.textSelStart !== editableNode.textSelEnd) {
+      return;
+    }
+
+    const value = editableNode.value;
+    const caretIndex = editableNode.textSelStart;
+    const leftOfCaret = value.substring(0, caretIndex);
+    const rightOfCaret = value.substring(caretIndex);
+    phrase = phrase.toLowerCase().trim();
+
+    // Require `phrase` to be separated by word boundaries and prefer the
+    // RegExps that include a leading/trailing space to preserve spacing.
+    const lastPhrase = new RegExp(`(\\b${phrase}\\b)(?!.*\\b\\1\\b)`, 'i');
+    const lastPhraseLeadingSpace =
+        new RegExp(`(\\b ${phrase}\\b)(?!.*\\b\\1\\b)`, 'i');
+    const lastPhraseTrailingSpace =
+        new RegExp(`(\\b${phrase} \\b)(?!.*\\b\\1\\b)`, 'i');
+
+    let newLeft;
+    if (lastPhraseLeadingSpace.test(leftOfCaret)) {
+      newLeft = leftOfCaret.replace(lastPhraseLeadingSpace, '');
+    } else if (lastPhraseTrailingSpace.test(leftOfCaret)) {
+      newLeft = leftOfCaret.replace(lastPhraseTrailingSpace, '');
+    } else {
+      newLeft = leftOfCaret.replace(lastPhrase, '');
+    }
+
+    const newValue = newLeft + rightOfCaret;
+    editableNode.setValue(newValue);
+  }
 }
 
 /**
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js
index c2ac19a..85c49be 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/hidden_macro_manager.js
@@ -5,6 +5,7 @@
 import {DeletePrevSentMacro} from '/accessibility_common/dictation/macros/delete_prev_sent_macro.js';
 import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js';
 import {DeletePrevWordMacro, NavNextWordMacro, NavPrevWordMacro} from '/accessibility_common/dictation/macros/repeatable_key_press_macro.js';
+import {SmartDeletePhraseMacro} from '/accessibility_common/dictation/macros/smart_delete_phrase_macro.js';
 import {StopListeningMacro} from '/accessibility_common/dictation/macros/stop_listening_macro.js';
 
 /**
@@ -40,7 +41,26 @@
         new NavPrevWordMacro(/*isRtlLocale=*/ false).runMacro();
         break;
       default:
-        throw new Error(`Unrecognized macro: ${name}`);
+        throw new Error(`Cannot run macro: ${name} for testing`);
+    }
+  }
+
+  /**
+   * @param {!MacroName} name The macro to run.
+   * @param {string} arg
+   */
+  runMacroWithStringArgForTesting(name, arg) {
+    if (!HiddenMacroManager.isHiddenMacro(name)) {
+      throw new Error('HiddenMacroManager can only invoke hidden macros.');
+    }
+
+    switch (name) {
+      case MacroName.SMART_DELETE_PHRASE:
+        new SmartDeletePhraseMacro(this.inputController_, arg).runMacro();
+        break;
+      default:
+        throw new Error(
+            `Cannot run macro: ${name} with string arg: ${arg} for testing`);
     }
   }
 
@@ -64,4 +84,5 @@
   MacroName.DELETE_PREV_SENT,
   MacroName.NAV_NEXT_WORD,
   MacroName.NAV_PREV_WORD,
+  MacroName.SMART_DELETE_PHRASE,
 ];
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
index eb97588..f63a558 100644
--- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/macro_names.js
@@ -82,5 +82,8 @@
   // Move the cursor to the previous word.
   NAV_PREV_WORD: 20,
 
+  // Deletes a provided word or phrase.
+  SMART_DELETE_PHRASE: 21,
+
   // Any new actions should match with Voice Access's semantic tags.
 };
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js
new file mode 100644
index 0000000..0f3fea966
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/dictation/macros/smart_delete_phrase_macro.js
@@ -0,0 +1,37 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {Macro} from '/accessibility_common/dictation/macros/macro.js';
+import {MacroName} from '/accessibility_common/dictation/macros/macro_names.js';
+
+/** Implements a macro that deletes a provided word or phrase. */
+export class SmartDeletePhraseMacro extends Macro {
+  /**
+   * @param {!InputController} inputController
+   * @param {string} phrase
+   */
+  constructor(inputController, phrase) {
+    super(MacroName.SMART_DELETE_PHRASE);
+    /** @private {!InputController} */
+    this.inputController_ = inputController;
+    /** @private {string} */
+    this.phrase_ = phrase;
+  }
+
+  /** @override */
+  checkContext() {
+    return this.createSuccessCheckContextResult_(
+        /*willImmediatelyDisambiguate=*/ false);
+  }
+
+  /** @override */
+  runMacro() {
+    if (!this.inputController_.isActive()) {
+      return this.createRunMacroResult_(
+          /*isSuccess=*/ false, MacroError.FAILED_ACTUATION);
+    }
+    this.inputController_.smartDeletePhrase(this.phrase_);
+    return this.createRunMacroResult_(/*isSuccess=*/ true);
+  }
+}
diff --git a/chrome/browser/resources/webui_gallery/BUILD.gn b/chrome/browser/resources/webui_gallery/BUILD.gn
index e6e105d..076c0ba3 100644
--- a/chrome/browser/resources/webui_gallery/BUILD.gn
+++ b/chrome/browser/resources/webui_gallery/BUILD.gn
@@ -32,6 +32,7 @@
     "demos/demo.css",
     "demos/cr_button_demo.html",
     "demos/cr_checkbox_demo.html",
+    "demos/cr_dialog_demo.html",
     "webui_gallery.html",
   ]
   input_files_base_dir = rebase_path(".", "//")
@@ -45,7 +46,7 @@
 
 copy("copy_ts_files") {
   sources = ts_files
-  outputs = [ "$target_gen_dir/{{source_file_part}}" ]
+  outputs = [ "$target_gen_dir/{{source_target_relative}}" ]
 }
 
 ts_library("build_ts") {
diff --git a/chrome/browser/resources/webui_gallery/app.ts b/chrome/browser/resources/webui_gallery/app.ts
index 8e8ad9f..a7999f4eb 100644
--- a/chrome/browser/resources/webui_gallery/app.ts
+++ b/chrome/browser/resources/webui_gallery/app.ts
@@ -33,6 +33,10 @@
             {
               name: 'cr-checkbox demo',
               url: 'cr_checkbox_demo.html',
+            },
+            {
+              name: 'cr-dialog demo',
+              url: 'cr_dialog_demo.html',
             }
           ];
         },
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html
new file mode 100644
index 0000000..4ea532e7
--- /dev/null
+++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>cr-dialog demo</title>
+    <link rel="stylesheet" href="demo.css">
+  <body>
+    <cr-dialog-demo></cr-dialog-demo>
+    <script src="cr_dialog_demo_component.js" type="module"></script>
+  </body>
+</html>
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html
new file mode 100644
index 0000000..600ef473
--- /dev/null
+++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.html
@@ -0,0 +1,78 @@
+<link rel="stylesheet" href="demo.css">
+
+<style>
+  cr-input:first-of-type {
+    margin-block-start: 16px;
+  }
+
+  [slot='header'] {
+    padding: 0 20px 16px;
+  }
+
+  cr-dialog::part(body-container) {
+    max-height: 300px;
+  }
+
+  #tallBlock {
+    background: var(--google-grey-200);
+    height: 800px;
+    margin: 16px 0;
+  }
+</style>
+
+<h1>cr-dialog</h1>
+<div class="demos">
+  <cr-checkbox checked="{{showHeader_}}">Show header</cr-checkbox>
+  <cr-checkbox checked="{{showFooter_}}">Show footer</cr-checkbox>
+  <cr-checkbox checked="{{showScrollingBody_}}">
+    Show tall scrolling body
+  </cr-checkbox>
+  <cr-checkbox checked="{{showInputs_}}">Show inputs</cr-checkbox>
+  <cr-checkbox checked="{{autofocusInput_}}" disabled$="[[!showInputs_]]">
+    Autofocus input when dialog opens
+  </cr-checkbox>
+
+  <cr-button on-click="openDialog_">Open dialog</cr-button>
+  <div>
+    <template is="dom-repeat" items="[[statusTexts_]]">
+      <div>[[item]]</div>
+    </template>
+  </div>
+</div>
+
+<template is="dom-if" if="[[isDialogOpen_]]" restamp>
+  <cr-dialog
+      id="dialog"
+      on-cr-dialog-open="onOpenDialog_"
+      on-cancel="onCancelDialog_"
+      on-close="onCloseDialog_"
+      show-on-attach>
+    <div slot="title">Dialog title</div>
+    <div slot="header" hidden$="[[!showHeader_]]">
+      Dialogs can also include a header between the title and the body. It is
+      commonly used to display status updates or tabs.
+    </div>
+    <div slot="body">
+      <div>Here is where some description text would go.</div>
+      <div hidden$="[[!showInputs_]]">
+        <cr-input label="Example input" autofocus$="[[autofocusInput_]]">
+        </cr-input>
+        <cr-input label="Example input"></cr-input>
+      </div>
+      <div hidden$="[[!showScrollingBody_]]">
+        <div id="tallBlock"></div>
+      </div>
+    </div>
+    <div slot="button-container">
+      <cr-button class="cancel-button" on-click="onClickCancel_">
+        Cancel
+      </cr-button>
+      <cr-button class="action-button" on-click="onClickConfirm_">
+        Confirm
+      </cr-button>
+    </div>
+    <div slot="footer" hidden$="[[!showFooter_]]">
+      Dialogs also have a slot for text or other elements in the footer.
+    </div>
+  </cr-dialog>
+</template>
\ No newline at end of file
diff --git a/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts
new file mode 100644
index 0000000..e4af0bda
--- /dev/null
+++ b/chrome/browser/resources/webui_gallery/demos/cr_dialog_demo_component.ts
@@ -0,0 +1,89 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
+import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
+import 'chrome://resources/cr_elements/shared_vars_css.m.js';
+
+import {PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+
+import {getTemplate} from './cr_dialog_demo_component.html.js';
+
+interface CrDialogDemoComponent {
+  $: {
+    dialog: CrDialogElement,
+  };
+}
+
+class CrDialogDemoComponent extends PolymerElement {
+  static get is() {
+    return 'cr-dialog-demo';
+  }
+
+  static get template() {
+    return getTemplate();
+  }
+
+  static get properties() {
+    return {
+      autofocusInputs_: Boolean,
+      isDialogOpen_: Boolean,
+      showHeader_: Boolean,
+      showFooter_: Boolean,
+      showInputs_: Boolean,
+      showScrollingBody_: Boolean,
+      statusTexts_: Array,
+    };
+  }
+
+  private autofocusInputs_: Boolean = false;
+  private isDialogOpen_: Boolean = false;
+  private showHeader_: Boolean = false;
+  private showFooter_: Boolean = false;
+  private showInputs_: Boolean = false;
+  private showScrollingBody_: Boolean = false;
+  private statusTexts_: string[] = [];
+
+  private getDialog_(): CrDialogElement|null {
+    return this.shadowRoot!.querySelector('cr-dialog');
+  }
+
+  private openDialog_() {
+    this.isDialogOpen_ = true;
+  }
+
+  private onClickCancel_() {
+    const dialog = this.getDialog_();
+    if (dialog) {
+      dialog.cancel();
+    }
+  }
+
+  private onClickConfirm_() {
+    const dialog = this.getDialog_();
+    if (dialog) {
+      dialog.close();
+    }
+  }
+
+  private onOpenDialog_() {
+    this.statusTexts_ =
+        ['Dialog was opened and fired a `cr-dialog-open` event.'];
+  }
+
+  private onCancelDialog_() {
+    this.push(
+        'statusTexts_', 'Dialog was canceled and fired a `cancel` event.');
+  }
+
+  private onCloseDialog_() {
+    this.isDialogOpen_ = false;
+    this.push('statusTexts_', 'Dialog was closed and fired a `close` event.');
+  }
+}
+
+customElements.define(CrDialogDemoComponent.is, CrDialogDemoComponent);
\ No newline at end of file
diff --git a/chrome/browser/resources/webui_gallery/webui_gallery.gni b/chrome/browser/resources/webui_gallery/webui_gallery.gni
index b11378e..4a3e313 100644
--- a/chrome/browser/resources/webui_gallery/webui_gallery.gni
+++ b/chrome/browser/resources/webui_gallery/webui_gallery.gni
@@ -3,7 +3,10 @@
 # found in the LICENSE file.
 
 # Files holding a Polymer element definition AND have an equivalent .html file.
-web_component_files = [ "app.ts" ]
+web_component_files = [
+  "app.ts",
+  "demos/cr_dialog_demo_component.ts",
+]
 
 # Files that are passed as input to html_to_wrapper().
 html_files = []
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.cc b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
index 5a75d2a..f8d4881 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.cc
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.cc
@@ -36,6 +36,7 @@
 
 sessions::LiveTabContext* ChromeTabRestoreServiceClient::CreateLiveTabContext(
     sessions::LiveTabContext* existing_context,
+    sessions::SessionWindow::WindowType type,
     const std::string& app_name,
     const gfx::Rect& bounds,
     ui::WindowShowState show_state,
@@ -48,8 +49,9 @@
   DCHECK(existing_context);
   return existing_context;
 #else
-  return BrowserLiveTabContext::Create(profile_, app_name, bounds, show_state,
-                                       workspace, user_title, extra_data);
+  return BrowserLiveTabContext::Create(profile_, type, app_name, bounds,
+                                       show_state, workspace, user_title,
+                                       extra_data);
 #endif
 }
 
diff --git a/chrome/browser/sessions/chrome_tab_restore_service_client.h b/chrome/browser/sessions/chrome_tab_restore_service_client.h
index 64f7fa8..764d202 100644
--- a/chrome/browser/sessions/chrome_tab_restore_service_client.h
+++ b/chrome/browser/sessions/chrome_tab_restore_service_client.h
@@ -26,6 +26,7 @@
   // TabRestoreServiceClient:
   sessions::LiveTabContext* CreateLiveTabContext(
       sessions::LiveTabContext* existing_context,
+      sessions::SessionWindow::WindowType type,
       const std::string& app_name,
       const gfx::Rect& bounds,
       ui::WindowShowState show_state,
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc
index b4f3be7..01392fd 100644
--- a/chrome/browser/sessions/session_restore_browsertest.cc
+++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -3717,9 +3717,10 @@
   web_app::AppId app_id2 = InstallPWA(profile, example_url2);
   web_app::AppId app_id3 = InstallPWA(profile, example_url3);
 
-  // Open all 3.
+  // Open all 3, browser 2 is app_popup.
   Browser* app_browser = web_app::LaunchWebAppBrowserAndWait(profile, app_id);
-  Browser* app_browser2 = web_app::LaunchWebAppBrowserAndWait(profile, app_id2);
+  Browser* app_browser2 = web_app::LaunchWebAppBrowserAndWait(
+      profile, app_id2, WindowOpenDisposition::NEW_POPUP);
   Browser* app_browser3 = web_app::LaunchWebAppBrowserAndWait(profile, app_id3);
 
   // 3 apps + basic browser.
@@ -3744,17 +3745,18 @@
   bool app3_seen = false;
   ASSERT_EQ(4u, BrowserList::GetInstance()->size());
   for (Browser* browser : *(BrowserList::GetInstance())) {
-    if (browser->type() == Browser::Type::TYPE_APP) {
-      if (web_app::AppBrowserController::IsForWebApp(browser, app_id)) {
-        EXPECT_FALSE(app1_seen);
-        app1_seen = true;
-      } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id2)) {
-        EXPECT_FALSE(app2_seen);
-        app2_seen = true;
-      } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id3)) {
-        EXPECT_FALSE(app3_seen);
-        app3_seen = true;
-      }
+    if (web_app::AppBrowserController::IsForWebApp(browser, app_id)) {
+      EXPECT_FALSE(app1_seen);
+      EXPECT_TRUE(browser->is_type_app());
+      app1_seen = true;
+    } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id2)) {
+      EXPECT_FALSE(app2_seen);
+      EXPECT_TRUE(browser->is_type_app_popup());
+      app2_seen = true;
+    } else if (web_app::AppBrowserController::IsForWebApp(browser, app_id3)) {
+      EXPECT_FALSE(app3_seen);
+      EXPECT_TRUE(browser->is_type_app());
+      app3_seen = true;
     }
   }
   EXPECT_TRUE(app1_seen);
diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc
index 36e375f..ef78287 100644
--- a/chrome/browser/sessions/tab_restore_service_unittest.cc
+++ b/chrome/browser/sessions/tab_restore_service_unittest.cc
@@ -70,6 +70,22 @@
 using ::testing::_;
 using ::testing::Return;
 
+class MockLiveTab : public sessions::LiveTab {
+ public:
+  MockLiveTab() = default;
+  ~MockLiveTab() override = default;
+
+  MOCK_METHOD0(IsInitialBlankNavigation, bool());
+  MOCK_METHOD0(GetCurrentEntryIndex, int());
+  MOCK_METHOD0(GetPendingEntryIndex, int());
+  MOCK_METHOD1(GetEntryAtIndex, sessions::SerializedNavigationEntry(int index));
+  MOCK_METHOD0(GetPendingEntry, sessions::SerializedNavigationEntry());
+  MOCK_METHOD0(GetEntryCount, int());
+  MOCK_METHOD0(GetPlatformSpecificTabData,
+               std::unique_ptr<sessions::PlatformSpecificTabData>());
+  MOCK_METHOD0(GetUserAgentOverride, sessions::SerializedUserAgentOverride());
+};
+
 class MockLiveTabContext : public sessions::LiveTabContext {
  public:
   MockLiveTabContext() = default;
@@ -77,6 +93,7 @@
 
   MOCK_METHOD0(ShowBrowserWindow, void());
   MOCK_CONST_METHOD0(GetSessionID, SessionID());
+  MOCK_CONST_METHOD0(GetWindowType, sessions::SessionWindow::WindowType());
   MOCK_CONST_METHOD0(GetTabCount, int());
   MOCK_CONST_METHOD0(GetSelectedIndex, int());
   MOCK_CONST_METHOD0(GetAppName, std::string());
@@ -135,9 +152,10 @@
   MockTabRestoreServiceClient() = default;
   ~MockTabRestoreServiceClient() override = default;
 
-  MOCK_METHOD7(CreateLiveTabContext,
+  MOCK_METHOD8(CreateLiveTabContext,
                sessions::LiveTabContext*(
                    sessions::LiveTabContext* existing_context,
+                   sessions::SessionWindow::WindowType type,
                    const std::string& app_name,
                    const gfx::Rect& bounds,
                    ui::WindowShowState show_state,
@@ -445,6 +463,60 @@
   ASSERT_EQ(kSampleValue, tab->extra_data[kSampleKey]);
 }
 
+// Ensure fields are written and read from saved state.
+TEST_F(TabRestoreServiceImplWithMockClientTest, WindowRestore) {
+  ON_CALL(*mock_tab_restore_service_client_, ShouldTrackURLForRestore(_))
+      .WillByDefault(Return(true));
+
+  SerializedNavigationEntry navigation_entry =
+      SerializedNavigationEntryTestHelper::CreateNavigationForTest();
+  testing::NiceMock<MockLiveTab> mock_live_tab;
+  ON_CALL(mock_live_tab, GetEntryCount).WillByDefault(Return(1));
+  ON_CALL(mock_live_tab, GetEntryAtIndex)
+      .WillByDefault(Return(navigation_entry));
+
+  testing::NiceMock<MockLiveTabContext> mock_live_tab_context;
+  SessionID session_id = SessionID::NewUnique();
+  ON_CALL(mock_live_tab_context, GetSessionID)
+      .WillByDefault(Return(session_id));
+  ON_CALL(mock_live_tab_context, GetWindowType)
+      .WillByDefault(Return(sessions::SessionWindow::TYPE_APP_POPUP));
+  ON_CALL(mock_live_tab_context, GetAppName).WillByDefault(Return("app-name"));
+  ON_CALL(mock_live_tab_context, GetUserTitle)
+      .WillByDefault(Return("user-title"));
+  ON_CALL(mock_live_tab_context, GetRestoredBounds)
+      .WillByDefault(Return(gfx::Rect(10, 20, 30, 40)));
+  ON_CALL(mock_live_tab_context, GetRestoredState)
+      .WillByDefault(Return(ui::SHOW_STATE_MAXIMIZED));
+  ON_CALL(mock_live_tab_context, GetWorkspace)
+      .WillByDefault(Return("workspace"));
+  ON_CALL(mock_live_tab_context, GetTabCount).WillByDefault(Return(1));
+  ON_CALL(mock_live_tab_context, GetLiveTabAt)
+      .WillByDefault(Return(&mock_live_tab));
+
+  service_->BrowserClosing(&mock_live_tab_context);
+
+  // Validate while entries are in memory.
+  auto validate = [&]() {
+    ASSERT_EQ(1u, service_->entries().size());
+    Entry* entry = service_->entries().front().get();
+    EXPECT_EQ(sessions::TabRestoreService::WINDOW, entry->type);
+    Window* window = static_cast<Window*>(entry);
+    EXPECT_EQ(sessions::SessionWindow::TYPE_APP_POPUP, window->type);
+    EXPECT_EQ(0, window->selected_tab_index);
+    EXPECT_EQ("app-name", window->app_name);
+    EXPECT_EQ("user-title", window->user_title);
+    EXPECT_EQ(gfx::Rect(10, 20, 30, 40), window->bounds);
+    EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, window->show_state);
+    EXPECT_EQ("workspace", window->workspace);
+  };
+  validate();
+
+  // Validate after persisting and reading from storage.
+  RecreateService();
+  validate();
+}
+
 // Make sure TabRestoreService doesn't create an entry for a tab with no
 // navigations.
 TEST_F(TabRestoreServiceImplTest, DontCreateEmptyTab) {
@@ -734,6 +806,7 @@
   ASSERT_EQ(sessions::TabRestoreService::WINDOW, entry2->type);
   sessions::TabRestoreService::Window* window =
       static_cast<sessions::TabRestoreService::Window*>(entry2);
+  EXPECT_EQ(sessions::SessionWindow::TYPE_NORMAL, window->type);
   ASSERT_EQ(1U, window->tabs.size());
   EXPECT_EQ(0, window->timestamp.ToDeltaSinceWindowsEpoch().InMicroseconds());
   EXPECT_EQ(0, window->selected_tab_index);
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc
index 446f40f1..fd3c36b 100644
--- a/chrome/browser/themes/browser_theme_pack.cc
+++ b/chrome/browser/themes/browser_theme_pack.cc
@@ -97,7 +97,7 @@
 // changed default theme assets, if you need themes to recreate their generated
 // images (which are cached), if you changed how missing values are
 // generated, or if you changed any constants.
-const int kThemePackVersion = 100;
+const int kThemePackVersion = 101;
 
 // IDs that are in the DataPack won't clash with the positive integer
 // uint16_t. kHeaderID should always have the maximum value because we want the
@@ -1129,8 +1129,7 @@
       {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE,
        kColorWindowControlButtonBackgroundActive},
       {TP::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE,
-       kColorWindowControlButtonBackgroundInactive},
-  };
+       kColorWindowControlButtonBackgroundInactive}};
 
   for (const auto& entry : kThemePropertiesMap) {
     SkColor color;
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc
index 11a0b68..0ea1acb 100644
--- a/chrome/browser/themes/theme_helper.cc
+++ b/chrome/browser/themes/theme_helper.cc
@@ -38,97 +38,6 @@
 // unpacked on the filesystem.)
 constexpr char kDefaultThemeGalleryID[] = "hkacjpbfdknhflllbcmjibkdeoafencn";
 
-// Returns an array of light and dark mode versions of the given color id
-// Ex: [light mode, dark mode]
-const std::array<SkColor, 2> GetTabGroupColors(int color_id) {
-  // Depending on UI variation enabled, dark mode saved group chip colors are
-  // calculated by blending the default dark mode toolbar color with the tab
-  // strip group colors at 24% or 48% alpha.
-  const SkColor default_dark_toolbar_color =
-      TP::GetDefaultColor(TP::COLOR_TOOLBAR, false, true);
-  float tab_group_chip_alpha = 0.24f;
-
-  // Flat version of dark mode colors used in bookmarks bar to fill
-  // the buttons.
-  const SkColor kFlatGrey = SkColorSetRGB(0x5D, 0x5E, 0x62);
-  const SkColor kFlatBlue = SkColorSetRGB(0x49, 0x54, 0x68);
-  const SkColor kFlatRed = SkColorSetRGB(0x62, 0x4A, 0x4B);
-  const SkColor kFlatGreen = SkColorSetRGB(0x47, 0x59, 0x50);
-  const SkColor kFlatYellow = SkColorSetRGB(0x65, 0x5C, 0x44);
-  const SkColor kFlatCyan = SkColorSetRGB(0x45, 0x5D, 0x65);
-  const SkColor kFlatPurple = SkColorSetRGB(0x58, 0x4A, 0x68);
-  const SkColor kFlatPink = SkColorSetRGB(0x65, 0x4A, 0x5D);
-  const SkColor kFlatOrange = color_utils::AlphaBlend(
-      gfx::kGoogleOrange300, default_dark_toolbar_color, tab_group_chip_alpha);
-
-  switch (color_id) {
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE:
-    case TP::COLOR_TAB_GROUP_DIALOG_BLUE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE:
-      return {gfx::kGoogleBlue600, gfx::kGoogleBlue300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE:
-      return {gfx::kGoogleBlue050, kFlatBlue};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED:
-    case TP::COLOR_TAB_GROUP_DIALOG_RED:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED:
-      return {gfx::kGoogleRed600, gfx::kGoogleRed300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED:
-      return {gfx::kGoogleRed050, kFlatRed};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW:
-    case TP::COLOR_TAB_GROUP_DIALOG_YELLOW:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW:
-      return {gfx::kGoogleYellow600, gfx::kGoogleYellow300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW:
-      return {gfx::kGoogleYellow050, kFlatYellow};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN:
-    case TP::COLOR_TAB_GROUP_DIALOG_GREEN:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN:
-      return {gfx::kGoogleGreen700, gfx::kGoogleGreen300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN:
-      return {gfx::kGoogleGreen050, kFlatGreen};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK:
-    case TP::COLOR_TAB_GROUP_DIALOG_PINK:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK:
-      return {gfx::kGooglePink700, gfx::kGooglePink300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK:
-      return {gfx::kGooglePink050, kFlatPink};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE:
-    case TP::COLOR_TAB_GROUP_DIALOG_PURPLE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE:
-      return {gfx::kGooglePurple500, gfx::kGooglePurple300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE:
-      return {gfx::kGooglePurple050, kFlatPurple};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN:
-    case TP::COLOR_TAB_GROUP_DIALOG_CYAN:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN:
-      return {gfx::kGoogleCyan900, gfx::kGoogleCyan300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN:
-      return {gfx::kGoogleCyan050, kFlatCyan};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE:
-    case TP::COLOR_TAB_GROUP_DIALOG_ORANGE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE:
-      return {gfx::kGoogleOrange400, gfx::kGoogleOrange300};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE:
-      return {gfx::kGoogleOrange050, kFlatOrange};
-    case TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY:
-      return {gfx::kGoogleGrey100, kFlatGrey};
-    case TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY:
-    case TP::COLOR_TAB_GROUP_DIALOG_GREY:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY:
-    case TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY:
-    default:
-      return {gfx::kGoogleGrey700, gfx::kGoogleGrey300};
-  }
-}
-
 SkColor IncreaseLightness(SkColor color, double percent) {
   color_utils::HSL result;
   color_utils::SkColorToHSL(color, &result);
@@ -314,10 +223,6 @@
     int id,
     bool incognito,
     const CustomThemeSupplier* theme_supplier) const {
-  if (TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY <= id &&
-      id <= TP::MAX_COLOR_BOOKMARK_BAR)
-    return GetTabGroupColor(id, incognito, theme_supplier);
-
   const absl::optional<SkColor> omnibox_color =
       GetOmniboxColor(id, incognito, theme_supplier);
   if (omnibox_color.has_value())
@@ -697,32 +602,3 @@
       return absl::nullopt;
   }
 }
-
-SkColor ThemeHelper::GetTabGroupColor(
-    int id,
-    bool incognito,
-    const CustomThemeSupplier* theme_supplier) const {
-  // Deal with tab group colors in the tabstrip.
-  if (id <= TP::MAX_COLOR_TABSTRIP_INACTIVE) {
-    int tab_color_id = id < TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY
-                           ? TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_ACTIVE
-                           : TP::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE;
-
-    return GetTabGroupColors(id)[color_utils::IsDark(
-        GetColor(tab_color_id, incognito, theme_supplier))];
-  }
-
-  // Deal with the rest of the tab group colors.
-  bool use_dark_mode_colors;
-  if (id >= TP::COLOR_TAB_GROUP_DIALOG_GREY &&
-      id <= TP::MAX_COLOR_BOOKMARK_BAR) {
-    // To support custom themes, assume that the dark mode palette is more
-    // appropriate for bookmark chips, tab group dialog bubble, and context sub
-    // menu when the bookmark bar appears to be light text on dark bookmark bar.
-    use_dark_mode_colors = !color_utils::IsDark(
-        GetColor(TP::COLOR_BOOKMARK_TEXT, incognito, theme_supplier));
-  } else {
-    use_dark_mode_colors = UseDarkModeColors(theme_supplier);
-  }
-  return GetTabGroupColors(id)[incognito || use_dark_mode_colors];
-}
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h
index 599ca7f..14a6806 100644
--- a/chrome/browser/themes/theme_properties.h
+++ b/chrome/browser/themes/theme_properties.h
@@ -179,71 +179,6 @@
     // kThemePackVersion in browser_theme_pack.cc, or else themes will display
     // incorrectly.
 
-    // Note: All tab group color ids must be grouped together consecutively and
-    // grouped together by use (eg grouped by dialog, context menu etc).
-    // This permits range checking and reduces redundant code. If you change or
-    // add to any of the below color ids, change the relevant code in
-    // ThemeHelper.
-
-    // The colors used for tab groups in the tabstrip.
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN,
-    COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE,
-    // The colors used for tab groups in the bubble dialog view.
-    COLOR_TAB_GROUP_DIALOG_GREY,
-    COLOR_TAB_GROUP_DIALOG_BLUE,
-    COLOR_TAB_GROUP_DIALOG_RED,
-    COLOR_TAB_GROUP_DIALOG_YELLOW,
-    COLOR_TAB_GROUP_DIALOG_GREEN,
-    COLOR_TAB_GROUP_DIALOG_PINK,
-    COLOR_TAB_GROUP_DIALOG_PURPLE,
-    COLOR_TAB_GROUP_DIALOG_CYAN,
-    COLOR_TAB_GROUP_DIALOG_ORANGE,
-    // The colors used for tab groups in the context submenu.
-    COLOR_TAB_GROUP_CONTEXT_MENU_GREY,
-    COLOR_TAB_GROUP_CONTEXT_MENU_BLUE,
-    COLOR_TAB_GROUP_CONTEXT_MENU_RED,
-    COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW,
-    COLOR_TAB_GROUP_CONTEXT_MENU_GREEN,
-    COLOR_TAB_GROUP_CONTEXT_MENU_PINK,
-    COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE,
-    COLOR_TAB_GROUP_CONTEXT_MENU_CYAN,
-    COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE,
-    // The colors used for saved tab group chips on the bookmark bar.
-    COLOR_TAB_GROUP_BOOKMARK_BAR_GREY,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_RED,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_PINK,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN,
-    COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE,
-    // If additional colors are ever added, update these references to those
-    // colors
-    MAX_COLOR_TABSTRIP_INACTIVE =
-        COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE,
-    MAX_COLOR_BOOKMARK_BAR = COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE,
-
-    // /!\ If you make any changes to this enum, you must also increment
-    // kThemePackVersion in browser_theme_pack.cc, or else themes will display
-    // incorrectly.
-
     // Calculated representative colors for the background of window control
     // buttons.
     COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_ACTIVE,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index 5d2c348a9..4c3ae66 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -212,79 +212,6 @@
        kColorTabForegroundInactiveFrameActive},
       {TP::COLOR_TAB_FOREGROUND_INACTIVE_FRAME_INACTIVE,
        kColorTabForegroundInactiveFrameInactive},
-      // The colors used for tab groups in the tabstrip.
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE,
-       kColorTabGroupTabStripFrameActiveBlue},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN,
-       kColorTabGroupTabStripFrameActiveCyan},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN,
-       kColorTabGroupTabStripFrameActiveGreen},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY,
-       kColorTabGroupTabStripFrameActiveGrey},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE,
-       kColorTabGroupTabStripFrameActiveOrange},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK,
-       kColorTabGroupTabStripFrameActivePink},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE,
-       kColorTabGroupTabStripFrameActivePurple},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED,
-       kColorTabGroupTabStripFrameActiveRed},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW,
-       kColorTabGroupTabStripFrameActiveYellow},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE,
-       kColorTabGroupTabStripFrameInactiveBlue},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN,
-       kColorTabGroupTabStripFrameInactiveCyan},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN,
-       kColorTabGroupTabStripFrameInactiveGreen},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY,
-       kColorTabGroupTabStripFrameInactiveGrey},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE,
-       kColorTabGroupTabStripFrameInactiveOrange},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK,
-       kColorTabGroupTabStripFrameInactivePink},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE,
-       kColorTabGroupTabStripFrameInactivePurple},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED,
-       kColorTabGroupTabStripFrameInactiveRed},
-      {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW,
-       kColorTabGroupTabStripFrameInactiveYellow},
-      // The colors used for tab groups in the bubble dialog view.
-      {TP::COLOR_TAB_GROUP_DIALOG_BLUE, kColorTabGroupDialogBlue},
-      {TP::COLOR_TAB_GROUP_DIALOG_CYAN, kColorTabGroupDialogCyan},
-      {TP::COLOR_TAB_GROUP_DIALOG_GREEN, kColorTabGroupDialogGreen},
-      {TP::COLOR_TAB_GROUP_DIALOG_GREY, kColorTabGroupDialogGrey},
-      {TP::COLOR_TAB_GROUP_DIALOG_ORANGE, kColorTabGroupDialogOrange},
-      {TP::COLOR_TAB_GROUP_DIALOG_PINK, kColorTabGroupDialogPink},
-      {TP::COLOR_TAB_GROUP_DIALOG_PURPLE, kColorTabGroupDialogPurple},
-      {TP::COLOR_TAB_GROUP_DIALOG_RED, kColorTabGroupDialogRed},
-      {TP::COLOR_TAB_GROUP_DIALOG_YELLOW, kColorTabGroupDialogYellow},
-      // The colors used for tab groups in the context submenu.
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE, kColorTabGroupContextMenuBlue},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN, kColorTabGroupContextMenuCyan},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN, kColorTabGroupContextMenuGreen},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY, kColorTabGroupContextMenuGrey},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK, kColorTabGroupContextMenuPink},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE,
-       kColorTabGroupContextMenuPurple},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE,
-       kColorTabGroupContextMenuOrange},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED, kColorTabGroupContextMenuRed},
-      {TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW,
-       kColorTabGroupContextMenuYellow},
-      // The colors used for saved tab group chips on the bookmark bar.
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE, kColorTabGroupBookmarkBarBlue},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN, kColorTabGroupBookmarkBarCyan},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN, kColorTabGroupBookmarkBarGreen},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY, kColorTabGroupBookmarkBarGrey},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE,
-       kColorTabGroupBookmarkBarOrange},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK, kColorTabGroupBookmarkBarPink},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE,
-       kColorTabGroupBookmarkBarPurple},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED, kColorTabGroupBookmarkBarRed},
-      {TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW,
-       kColorTabGroupBookmarkBarYellow},
       {TP::COLOR_TAB_STROKE_FRAME_ACTIVE, kColorTabStrokeFrameActive},
       {TP::COLOR_TAB_STROKE_FRAME_INACTIVE, kColorTabStrokeFrameInactive},
       // Toolbar and associated colors.
diff --git a/chrome/browser/themes/theme_service_test_utils.h b/chrome/browser/themes/theme_service_test_utils.h
index dc06778..e2f2bf7 100644
--- a/chrome/browser/themes/theme_service_test_utils.h
+++ b/chrome/browser/themes/theme_service_test_utils.h
@@ -27,7 +27,6 @@
      {ThemeProperties::COLOR_OMNIBOX_RESULTS_TEXT_SECONDARY_SELECTED, 1},
      {ThemeProperties::COLOR_STATUS_BUBBLE_INACTIVE, 1},
      {ThemeProperties::COLOR_TAB_BACKGROUND_INACTIVE_FRAME_INACTIVE, 1},
-     {ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE, 1},
      {ThemeProperties::COLOR_TAB_STROKE_FRAME_INACTIVE, 1},
      {ThemeProperties::COLOR_TOOLBAR_TOP_SEPARATOR_FRAME_INACTIVE, 1},
      {ThemeProperties::COLOR_WINDOW_CONTROL_BUTTON_BACKGROUND_INACTIVE, 1}});
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
index 8288dfe..6ef8b508 100644
--- a/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
+++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "components/sessions/content/content_live_tab.h"
 #include "components/sessions/content/content_serialized_navigation_builder.h"
+#include "components/sessions/core/session_types.h"
 #include "components/tab_groups/tab_group_id.h"
 #include "components/tab_groups/tab_group_visual_data.h"
 #include "content/public/browser/browser_context.h"
@@ -29,6 +30,12 @@
   return tab_model_->GetSessionId();
 }
 
+sessions::SessionWindow::WindowType AndroidLiveTabContext::GetWindowType()
+    const {
+  // Not applicable to android.
+  return sessions::SessionWindow::TYPE_NORMAL;
+}
+
 int AndroidLiveTabContext::GetTabCount() const {
   return tab_model_->GetTabCount();
 }
diff --git a/chrome/browser/ui/android/tab_model/android_live_tab_context.h b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
index c14b1a4..bf27884 100644
--- a/chrome/browser/ui/android/tab_model/android_live_tab_context.h
+++ b/chrome/browser/ui/android/tab_model/android_live_tab_context.h
@@ -33,6 +33,7 @@
   // Overridden from LiveTabContext:
   void ShowBrowserWindow() override;
   SessionID GetSessionID() const override;
+  sessions::SessionWindow::WindowType GetWindowType() const override;
   int GetTabCount() const override;
   int GetSelectedIndex() const override;
   std::string GetAppName() const override;
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java
index ca95779..29dd13e1 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ButtonData.java
@@ -11,6 +11,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.StringRes;
 
+import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures;
 import org.chromium.chrome.browser.toolbar.adaptive.AdaptiveToolbarFeatures.AdaptiveToolbarButtonVariant;
 import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
 
@@ -49,6 +50,7 @@
         private final IPHCommandBuilder mIPHCommandBuilder;
         @AdaptiveToolbarButtonVariant
         private final int mButtonVariant;
+        private final boolean mIsDynamicAction;
 
         public ButtonSpec(@NonNull Drawable drawable, @NonNull View.OnClickListener onClickListener,
                 @Nullable View.OnLongClickListener onLongClickListener, int contentDescriptionResId,
@@ -61,6 +63,7 @@
             mSupportsTinting = supportsTinting;
             mIPHCommandBuilder = iphCommandBuilder;
             mButtonVariant = buttonVariant;
+            mIsDynamicAction = AdaptiveToolbarFeatures.isDynamicAction(mButtonVariant);
         }
 
         /** Returns the {@link Drawable} for the button icon. */
@@ -107,5 +110,10 @@
         public int getButtonVariant() {
             return mButtonVariant;
         }
+
+        /** Returns {@code true} if the button is a contextual page action. False otherwise. */
+        public boolean isDynamicAction() {
+            return mIsDynamicAction;
+        }
     }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
index 8251bd1..17a0a0b 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarButtonController.java
@@ -167,7 +167,8 @@
         if (receivedButtonData == null) return null;
 
         if (!mIsSessionVariantRecorded && receivedButtonData.canShow()
-                && receivedButtonData.isEnabled()) {
+                && receivedButtonData.isEnabled()
+                && !receivedButtonData.getButtonSpec().isDynamicAction()) {
             mIsSessionVariantRecorded = true;
             RecordHistogram.recordEnumeratedHistogram(
                     "Android.AdaptiveToolbarButton.SessionVariant",
@@ -270,4 +271,11 @@
             });
         }
     }
+
+    /** Called to notify the controller that a dynamic action is available and should be shown. */
+    public void showDynamicAction(@AdaptiveToolbarButtonVariant int action) {
+        // TODO(shaktisahu): Fix logic to show the next preferred button.
+        setSingleProvider(mButtonDataProviderMap.get(action));
+        notifyObservers(action != AdaptiveToolbarButtonVariant.UNKNOWN);
+    }
 }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
index 685f027..c06bfdc 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarFeatures.java
@@ -86,10 +86,25 @@
         int VOICE = 4;
         int AUTO = 5;
         int PRICE_TRACKING = 6;
-
         int NUM_ENTRIES = 7;
     }
 
+    /** @return Whether the button variant is a dynamic action. */
+    public static boolean isDynamicAction(@AdaptiveToolbarButtonVariant int variant) {
+        switch (variant) {
+            case AdaptiveToolbarButtonVariant.UNKNOWN:
+            case AdaptiveToolbarButtonVariant.NONE:
+            case AdaptiveToolbarButtonVariant.NEW_TAB:
+            case AdaptiveToolbarButtonVariant.SHARE:
+            case AdaptiveToolbarButtonVariant.VOICE:
+            case AdaptiveToolbarButtonVariant.AUTO:
+                return false;
+            case AdaptiveToolbarButtonVariant.PRICE_TRACKING:
+                return true;
+        }
+        return false;
+    }
+
     /**
      * Returns whether the adaptive toolbar is enabled in single variant mode. Returns true also to
      * provide legacy support for feature flags {@code ShareButtonInTopToolbar} and {@code
@@ -128,6 +143,15 @@
     }
 
     /**
+     * @return Whether contextual page actions are enabled.
+     */
+    public static boolean isContextualPageActionUiEnabled() {
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.CONTEXTUAL_PAGE_ACTIONS)
+                && ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                        ChromeFeatureList.CONTEXTUAL_PAGE_ACTIONS, "enable_ui", true);
+    }
+
+    /**
      * When the adaptive toolbar is configured in a single button variant mode, returns the {@link
      * AdaptiveToolbarButtonVariant} being used.
      *
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
index afa4b617..206eeb9 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveToolbarStatePredictor.java
@@ -220,8 +220,7 @@
      * Conversion method between {@link SegmentId} and {@link
      * AdaptiveToolbarButtonVariant}.
      */
-    @VisibleForTesting
-    static @AdaptiveToolbarButtonVariant int getAdaptiveToolbarButtonVariantFromSegmentId(
+    public static @AdaptiveToolbarButtonVariant int getAdaptiveToolbarButtonVariantFromSegmentId(
             SegmentId segmentId) {
         switch (segmentId) {
             case OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB:
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 54fb554..9e3813b 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -223,11 +223,13 @@
 const char kPlayStorePackage[] = "com.android.vending";
 
 // App IDs, kept in sorted order.
+const char kAndroidContactsAppId[] = "kipfkokfekalckplgaikemhghlbkgpfl";
 const char kGmailAppId[] = "hhkfkjpmacfncmbapfohfocpjpdnobjg";
 const char kGoogleCalendarAppId[] = "decaoeahkmjpajbmlbpogjjkjbjokeed";
 const char kGoogleDuoAppId[] = "djkcbcmkefiiphjkonbeknmcgiheajce";
 const char kGoogleMapsAppId[] = "gmhipfhgnoelkiiofcnimehjnpaejiel";
 const char kGooglePhotosAppId[] = "fdbkkojdbojonckghlanfaopfakedeca";
+const char kGoogleTVAppId[] = "kadljooblnjdohjelobhphgeimdbcpbo";
 const char kInfinitePainterAppId[] = "afihfgfghkmdmggakhkgnfhlikhdpima";
 const char kLightRoomAppId[] = "fpegfnbgomakooccabncdaelhfppceni";
 const char kPlayBooksAppId[] = "cafegjnmmjpfibnlddppihpnkbkgicbg";
@@ -239,7 +241,6 @@
 const char kYoutubeAppId[] = "aniolghapcdkoolpkffememnhpphmjkl";
 const char kYoutubeMusicAppId[] = "hpdkdmlckojaocbedhffglopeafcgggc";
 const char kYoutubeMusicWebApkAppId[] = "jcmmigapnpnikbmnjknhcoageaeinihi";
-const char kAndroidContactsAppId[] = "kipfkokfekalckplgaikemhghlbkgpfl";
 
 bool ShouldShowInLauncher(const std::string& app_id) {
   for (auto* const id : kAppIdsHiddenInLauncher) {
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h
index 39f4c30..c8d93e6 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -28,12 +28,14 @@
 extern const char kPlayStoreActivity[];
 extern const char kPlayStorePackage[];
 
+extern const char kAndroidContactsAppId[];
 extern const char kCameraMigrationAppId[];
 extern const char kGmailAppId[];
 extern const char kGoogleCalendarAppId[];
 extern const char kGoogleDuoAppId[];
 extern const char kGoogleMapsAppId[];
 extern const char kGooglePhotosAppId[];
+extern const char kGoogleTVAppId[];
 extern const char kInfinitePainterAppId[];
 extern const char kLightRoomAppId[];
 extern const char kPlayBooksAppId[];
@@ -45,7 +47,6 @@
 extern const char kYoutubeAppId[];
 extern const char kYoutubeMusicAppId[];
 extern const char kYoutubeMusicWebApkAppId[];
-extern const char kAndroidContactsAppId[];
 
 // Observes ARC app launches.
 class AppLaunchObserver : public base::CheckedObserver {
diff --git a/chrome/browser/ui/ash/desks/desks_client.cc b/chrome/browser/ui/ash/desks/desks_client.cc
index 56c3e4e2..5539ce8 100644
--- a/chrome/browser/ui/ash/desks/desks_client.cc
+++ b/chrome/browser/ui/ash/desks/desks_client.cc
@@ -45,7 +45,7 @@
     "The maximum number of desks is already open.";
 constexpr char kMissingTemplateDataError[] =
     "The desk template has invalid or missing data.";
-constexpr char kStorageError[] = "The operation failed due to a storage error.";
+constexpr char kStorageError[] = "Storage error.";
 constexpr char kNoCurrentUserError[] = "There is no active profile.";
 constexpr char kBadProfileError[] =
     "Either the profile is not valid or there is not an active proflile.";
@@ -292,8 +292,10 @@
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
 }
 
-void DesksClient::LaunchDeskTemplate(const std::string& template_uuid,
-                                     LaunchDeskTemplateCallback callback) {
+void DesksClient::LaunchDeskTemplate(
+    const std::string& template_uuid,
+    LaunchDeskCallback callback,
+    const std::u16string& customized_desk_name) {
   base::Time launch_started = base::Time::Now();
 
   if (!active_profile_) {
@@ -303,16 +305,26 @@
 
   if (launch_template_for_test_) {
     OnGetTemplateForDeskLaunch(
-        std::move(callback), base::Time(),
+        std::move(callback), customized_desk_name, base::Time(),
         desks_storage::DeskModel::GetEntryByUuidStatus::kOk,
         launch_template_for_test_->Clone());
     return;
   }
 
   GetDeskModel()->GetEntryByUUID(
-      template_uuid, base::BindOnce(&DesksClient::OnGetTemplateForDeskLaunch,
-                                    weak_ptr_factory_.GetWeakPtr(),
-                                    std::move(callback), launch_started));
+      template_uuid,
+      base::BindOnce(&DesksClient::OnGetTemplateForDeskLaunch,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback),
+                     customized_desk_name, launch_started));
+}
+
+void DesksClient::LaunchEmptyDesk(LaunchDeskCallback callback,
+                                  const std::u16string& customized_desk_name) {
+  desks_controller_->CreateNewDeskForTemplate(
+      /*activate_desk=*/true,
+      base::BindOnce(&DesksClient::OnLaunchEmptyDesk,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback)),
+      customized_desk_name);
 }
 
 void DesksClient::RemoveDesk(const base::GUID& desk_uuid,
@@ -342,7 +354,7 @@
     return;
   }
 
-  std::move(callback).Run("");
+  std::move(callback).Run(/*error=*/"");
 }
 
 void DesksClient::GetAllDesks(GetAllDesksCallback callback) {
@@ -465,7 +477,8 @@
 }
 
 void DesksClient::OnGetTemplateForDeskLaunch(
-    LaunchDeskTemplateCallback callback,
+    LaunchDeskCallback callback,
+    std::u16string customized_desk_name,
     base::Time time_launch_started,
     desks_storage::DeskModel::GetEntryByUuidStatus status,
     std::unique_ptr<ash::DeskTemplate> entry) {
@@ -477,15 +490,20 @@
   const auto template_name = entry->template_name();
   const bool activate_desk = entry->type() == ash::DeskTemplateType::kTemplate;
   desks_controller_->CreateNewDeskForTemplate(
-      template_name, activate_desk,
-      base::BindOnce(&DesksClient::OnCreateAndActivateNewDesk,
+      activate_desk,
+      base::BindOnce(&DesksClient::OnCreateAndActivateNewDeskForTemplate,
                      weak_ptr_factory_.GetWeakPtr(), std::move(entry),
-                     std::move(callback), time_launch_started));
+                     std::move(callback), time_launch_started),
+      // We prioritize `customized_desk_name` over `template_name`. An example
+      // is that for call center application use case, we launch the same
+      // template for different customer and assign desk name to be customer's
+      // name.
+      customized_desk_name.empty() ? template_name : customized_desk_name);
 }
 
-void DesksClient::OnCreateAndActivateNewDesk(
+void DesksClient::OnCreateAndActivateNewDeskForTemplate(
     std::unique_ptr<ash::DeskTemplate> desk_template,
-    LaunchDeskTemplateCallback callback,
+    LaunchDeskCallback callback,
     base::Time time_launch_started,
     const ash::Desk* new_desk) {
   if (new_desk == nullptr) {
@@ -509,6 +527,17 @@
   std::move(callback).Run("", new_desk->uuid());
 }
 
+void DesksClient::OnLaunchEmptyDesk(LaunchDeskCallback callback,
+                                    const ash::Desk* new_desk) {
+  if (!new_desk) {
+    // This will only fail if the number of desks is at a maximum.
+    std::move(callback).Run(kMaximumDesksOpenedError, {});
+    return;
+  }
+
+  std::move(callback).Run(/*error=*/"", new_desk->uuid());
+}
+
 void DesksClient::OnCaptureActiveDeskAndSaveTemplate(
     DesksClient::CaptureActiveDeskAndSaveTemplateCallback callback,
     std::unique_ptr<ash::DeskTemplate> desk_template,
diff --git a/chrome/browser/ui/ash/desks/desks_client.h b/chrome/browser/ui/ash/desks/desks_client.h
index 89a45f8..69a4247 100644
--- a/chrome/browser/ui/ash/desks/desks_client.h
+++ b/chrome/browser/ui/ash/desks/desks_client.h
@@ -109,17 +109,28 @@
                        Profile* profile,
                        GetTemplateJsonCallback callback);
 
-  using LaunchDeskTemplateCallback =
+  using LaunchDeskCallback =
       base::OnceCallback<void(std::string error, const base::GUID& desk_uuid)>;
-  // Launches the desk template with |template_uuid| as a new desk.
-  // |template_uuid| should be the unique id for an existing desk template. If
+  // Launches the desk template with `template_uuid` as a new desk.
+  // `template_uuid` should be the unique id for an existing desk template. If
   // no such id can be found or we are at the max desk limit (currently is 8)
-  // so can't create new desk for the desk template, |callback| will be invoked
-  // with a description of the error and the new desk uuid.
+  // so can't create new desk for the desk template, `callback` will be invoked
+  // with a description of the error and the new desk uuid. If
+  // `customized_desk_name` is provided, desk name will be set to
+  // `customized_desk_name` or `customized_desk_name ({counter})` to resolve
+  // naming conflicts. Otherwise, desk name will be set to auto generated name.
   // TODO(crbug.com/1286515): This will be removed with the extension. Avoid
   // further uses of this method.
-  void LaunchDeskTemplate(const std::string& template_uuid,
-                          LaunchDeskTemplateCallback callback);
+  void LaunchDeskTemplate(
+      const std::string& template_uuid,
+      LaunchDeskCallback callback,
+      const std::u16string& customized_desk_name = std::u16string());
+
+  // Launches an empty new desk. Desk name will be set to `customized_desk_name`
+  // variant if it's provided, otherwise will be set to auto generated name.
+  void LaunchEmptyDesk(
+      LaunchDeskCallback callback,
+      const std::u16string& customized_desk_name = std::u16string());
 
   using CloseAllCallBack = base::OnceCallback<void(std::string error)>;
   // Remove a desk, close all windows if `close_all` set to true, otherwise
@@ -154,19 +165,25 @@
 
   // Launches DeskTemplate after retrieval from storage.
   void OnGetTemplateForDeskLaunch(
-      LaunchDeskTemplateCallback callback,
+      LaunchDeskCallback callback,
+      std::u16string customized_desk_name,
       base::Time time_launch_started,
       desks_storage::DeskModel::GetEntryByUuidStatus status,
       std::unique_ptr<ash::DeskTemplate> entry);
 
-  // Callback function that is ran after a desk is created, or has failed to be
-  // created.
-  void OnCreateAndActivateNewDesk(
+  // Callback function that is run after a desk is created for a template, or
+  // has failed to be created.
+  void OnCreateAndActivateNewDeskForTemplate(
       std::unique_ptr<ash::DeskTemplate> desk_template,
-      LaunchDeskTemplateCallback callback,
+      LaunchDeskCallback callback,
       base::Time time_launch_started,
       const ash::Desk* new_desk);
 
+  // Callback function that is run after a desk is created, or has failed to
+  // be created.
+  void OnLaunchEmptyDesk(LaunchDeskCallback callback,
+                         const ash::Desk* new_desk);
+
   // Callback function that allows the |CaptureActiveDeskAndSaveTemplate|
   // |callback| to be called as a |desks_storage::AddOrUpdateEntryCallback|.
   void OnCaptureActiveDeskAndSaveTemplate(
diff --git a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
index 6544080..75d0538 100644
--- a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
+++ b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
@@ -43,6 +43,7 @@
 #include "chrome/browser/ash/profiles/profile_helper.h"
 #include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
 #include "chrome/browser/ash/system_web_apps/types/system_web_app_type.h"
+#include "chrome/browser/extensions/extension_apitest.h"
 #include "chrome/browser/policy/policy_test_utils.h"
 #include "chrome/browser/prefs/session_startup_pref.h"
 #include "chrome/browser/profiles/keep_alive/profile_keep_alive_types.h"
@@ -2107,6 +2108,53 @@
       }));
 }
 
+// Tests launch an empty desk with `desk_name` provided.
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchEmptyDeskWithProvidedName) {
+  auto* desks_controller = ash::DesksController::Get();
+  // Should have 1 default active desk.
+  EXPECT_EQ(1, desks_controller->desks().size());
+
+  base::RunLoop loop;
+  std::u16string desk_name(u"test");
+  DesksClient::Get()->LaunchEmptyDesk(
+      base::BindLambdaForTesting(
+          [&](std::string error, const base::GUID& desk_uuid) {
+            EXPECT_TRUE(error.empty());
+            // Launch one template, desk size should increase by 1.
+            EXPECT_EQ(2, desks_controller->desks().size());
+            // `desk_name` should be set as provided
+            EXPECT_EQ(desk_name, desks_controller->desks().back()->name());
+            // `desk_uuid` should be returned.
+            EXPECT_TRUE(desk_uuid.AsLowercaseString().size() > 0);
+            loop.Quit();
+          }),
+      desk_name);
+  loop.Run();
+}
+
+// Tests launch an empty desk with default name.
+IN_PROC_BROWSER_TEST_F(DesksTemplatesClientTest,
+                       LaunchEmptyDeskWithDefaultName) {
+  auto* desks_controller = ash::DesksController::Get();
+  // Should have 1 default active desk.
+  EXPECT_EQ(1, desks_controller->desks().size());
+
+  base::RunLoop loop;
+  DesksClient::Get()->LaunchEmptyDesk(base::BindLambdaForTesting(
+      [&](std::string error, const base::GUID& desk_uuid) {
+        EXPECT_TRUE(error.empty());
+        // Launch one template, desk size should increase by 1.
+        EXPECT_EQ(2, desks_controller->desks().size());
+        // `desk_name` should be set as default desk name
+        EXPECT_EQ(u"Desk 2", desks_controller->desks().back()->name());
+        // `desk_uuid` should be returned.
+        EXPECT_TRUE(desk_uuid.AsLowercaseString().size() > 0);
+        loop.Quit();
+      }));
+  loop.Run();
+}
+
 class DesksTemplatesClientArcTest : public InProcessBrowserTest {
  public:
   DesksTemplatesClientArcTest() {
@@ -2360,3 +2408,10 @@
   EXPECT_FALSE(
       ContainUuidInTemplates(kTestAdminTemplateUuid, GetDeskTemplates()));
 }
+
+using DesksExtensionApiTest = extensions::ExtensionApiTest;
+IN_PROC_BROWSER_TEST_F(DesksExtensionApiTest, TestDesksClientExtension) {
+  // This loads and runs an extension from
+  // chrome/test/data/extensions/api_test/wm_desks_private.
+  ASSERT_TRUE(RunExtensionTest("wm_desks_private"));
+}
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
index 9072920..d8354be 100644
--- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -30,14 +30,14 @@
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 // Internal builds add an extra accelerator for the Feedback app.
 // The total number of Chrome accelerators (available on Chrome OS).
-constexpr int kChromeAcceleratorsTotalNum = 102;
+constexpr int kChromeAcceleratorsTotalNum = 103;
 // The hash of Chrome accelerators (available on Chrome OS).
-constexpr char kChromeAcceleratorsHash[] = "672b2d00632c66337b6323da9c75e3a2";
+constexpr char kChromeAcceleratorsHash[] = "c4e99672a6945b80f84be385899c7fa5";
 #else
 // The total number of Chrome accelerators (available on Chrome OS).
-constexpr int kChromeAcceleratorsTotalNum = 101;
+constexpr int kChromeAcceleratorsTotalNum = 102;
 // The hash of Chrome accelerators (available on Chrome OS).
-constexpr char kChromeAcceleratorsHash[] = "7143dc8ef5efe3fc6047e864f589386f";
+constexpr char kChromeAcceleratorsHash[] = "9a7ba4b726beaba00d7e038ea2ed9c53";
 #endif  // BUILDFLAG(GOOGLE_CHROME_BRANDING)
 
 const char* BooleanToString(bool value) {
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index b292a6b1..c582ceb8 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -105,6 +105,16 @@
 #include "ui/ozone/public/ozone_platform.h"
 #endif
 
+// TODO(https://crbug.com/1331331): Clean this up after the deprecation period.
+#if BUILDFLAG(ENABLE_PRINTING)
+#include "chrome/browser/infobars/simple_alert_infobar_creator.h"
+#include "chrome/browser/ui/accelerator_utils.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/infobars/content/content_infobar_manager.h"
+#include "components/vector_icons/vector_icons.h"
+#include "ui/base/l10n/l10n_util.h"
+#endif
+
 using WebExposedIsolationLevel =
     content::RenderFrameHost::WebExposedIsolationLevel;
 
@@ -160,6 +170,28 @@
   return true;
 }
 
+#if BUILDFLAG(ENABLE_PRINTING)
+// TODO(https://crbug.com/1331331): Clean this up after the deprecation period.
+void ShowDeprecatedBasicPrintInfoBar(Browser* browser) {
+  ui::AcceleratorProvider* provider =
+      chrome::AcceleratorProviderForBrowser(browser);
+
+  ui::Accelerator accelerator;
+  bool success =
+      provider->GetAcceleratorForCommandId(IDC_BASIC_PRINT, &accelerator);
+  DCHECK(success);
+
+  auto message = l10n_util::GetStringFUTF16(
+      IDS_PRINT_BASIC_SHORTCUT_DEPRECATION_TEXT, accelerator.GetShortcutText());
+  CreateSimpleAlertInfoBar(
+      infobars::ContentInfoBarManager::FromWebContents(
+          browser->tab_strip_model()->GetActiveWebContents()),
+      infobars::InfoBarDelegate::BASIC_PRINT_DEPRECATED_ACCELERATOR_DELEGATE,
+      &vector_icons::kWarningIcon, message,
+      /*auto_expire=*/false, /*should_animate=*/true);
+}
+#endif  // BUILDFLAG(ENABLE_PRINTING)
+
 }  // namespace
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -576,6 +608,9 @@
       break;
 
 #if BUILDFLAG(ENABLE_PRINTING)
+    case IDC_BASIC_PRINT_DEPRECATED:
+      ShowDeprecatedBasicPrintInfoBar(browser_);
+      [[fallthrough]];
     case IDC_BASIC_PRINT:
       base::RecordAction(base::UserMetricsAction("Accel_Advanced_Print"));
       BasicPrint(browser_);
@@ -1594,6 +1629,8 @@
   bool print_enabled = CanPrint(browser_);
   command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled);
 #if BUILDFLAG(ENABLE_PRINTING)
+  command_updater_.UpdateCommandEnabled(IDC_BASIC_PRINT_DEPRECATED,
+                                        CanBasicPrint(browser_));
   command_updater_.UpdateCommandEnabled(IDC_BASIC_PRINT,
                                         CanBasicPrint(browser_));
 #endif
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc
index ee8f5ff..7b38682 100644
--- a/chrome/browser/ui/browser_live_tab_context.cc
+++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/sessions/closed_tab_cache.h"
 #include "chrome/browser/sessions/closed_tab_cache_service_factory.h"
+#include "chrome/browser/sessions/session_service_utils.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -29,6 +30,7 @@
 #include "chrome/common/buildflags.h"
 #include "components/sessions/content/content_live_tab.h"
 #include "components/sessions/content/content_platform_specific_tab_data.h"
+#include "components/sessions/core/session_types.h"
 #include "components/tab_groups/tab_group_id.h"
 #include "components/tab_groups/tab_group_visual_data.h"
 #include "content/public/browser/navigation_controller.h"
@@ -76,6 +78,11 @@
   return browser_->session_id();
 }
 
+sessions::SessionWindow::WindowType BrowserLiveTabContext::GetWindowType()
+    const {
+  return WindowTypeForBrowserType(browser_->type());
+}
+
 int BrowserLiveTabContext::GetTabCount() const {
   return browser_->tab_strip_model()->count();
 }
@@ -282,6 +289,7 @@
 // static
 sessions::LiveTabContext* BrowserLiveTabContext::Create(
     Profile* profile,
+    sessions::SessionWindow::WindowType type,
     const std::string& app_name,
     const gfx::Rect& bounds,
     ui::WindowShowState show_state,
@@ -291,10 +299,17 @@
   std::unique_ptr<Browser::CreateParams> create_params;
   if (ShouldCreateAppWindowForAppName(profile, app_name)) {
     // Only trusted app popup windows should ever be restored.
-    create_params = std::make_unique<Browser::CreateParams>(
-        Browser::CreateParams::CreateForApp(app_name, true /* trusted_source */,
-                                            bounds, profile,
-                                            true /* user_gesture */));
+    if (type == sessions::SessionWindow::TYPE_APP_POPUP) {
+      create_params = std::make_unique<Browser::CreateParams>(
+          Browser::CreateParams::CreateForAppPopup(
+              app_name, /*trusted_source=*/true, bounds, profile,
+              /*user_gesture=*/true));
+    } else {
+      create_params = std::make_unique<Browser::CreateParams>(
+          Browser::CreateParams::CreateForApp(app_name, /*trusted_source=*/true,
+                                              bounds, profile,
+                                              /*user_gesture=*/true));
+    }
   } else {
     create_params = std::make_unique<Browser::CreateParams>(
         Browser::CreateParams(profile, true));
diff --git a/chrome/browser/ui/browser_live_tab_context.h b/chrome/browser/ui/browser_live_tab_context.h
index e9eeed4..2c06347c 100644
--- a/chrome/browser/ui/browser_live_tab_context.h
+++ b/chrome/browser/ui/browser_live_tab_context.h
@@ -40,6 +40,7 @@
   // Overridden from LiveTabContext:
   void ShowBrowserWindow() override;
   SessionID GetSessionID() const override;
+  sessions::SessionWindow::WindowType GetWindowType() const override;
   int GetTabCount() const override;
   int GetSelectedIndex() const override;
   std::string GetAppName() const override;
@@ -86,6 +87,7 @@
   // see Browser::Create
   static sessions::LiveTabContext* Create(
       Profile* profile,
+      sessions::SessionWindow::WindowType type,
       const std::string& app_name,
       const gfx::Rect& bounds,
       ui::WindowShowState show_state,
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge.mm b/chrome/browser/ui/cocoa/history_menu_bridge.mm
index 0b6a8b9b..8bc0261 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge.mm
@@ -30,6 +30,7 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/color/color_provider.h"
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/image/image_skia.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
@@ -345,11 +346,11 @@
   // Set the icon of the group to the group color circle.
   AppController* controller =
       base::mac::ObjCCastStrict<AppController>([NSApp delegate]);
-  const auto& theme = [controller lastActiveThemeProvider];
-  const int color_id =
-      GetTabGroupContextMenuColorIdDeprecated(group->visual_data.color());
+  const auto& color_provider = [controller lastActiveColorProvider];
+  const ui::ColorId color_id =
+      GetTabGroupContextMenuColorId(group->visual_data.color());
   gfx::ImageSkia group_icon = gfx::CreateVectorIcon(
-      kTabGroupIcon, gfx::kFaviconSize, theme.GetColor(color_id));
+      kTabGroupIcon, gfx::kFaviconSize, color_provider.GetColor(color_id));
 
   // Create the submenu.
   base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] init]);
diff --git a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
index d386d34..55e367c1 100644
--- a/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
+++ b/chrome/browser/ui/cocoa/history_menu_bridge_unittest.mm
@@ -68,7 +68,6 @@
  protected:
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
-
     appController_.reset([[AppController alloc] init]);
     [appController_ setLastProfileForTesting:profile()];
     previousApplicationDelegate_ = [NSApp delegate];
diff --git a/chrome/browser/ui/color/chrome_color_id.h b/chrome/browser/ui/color/chrome_color_id.h
index 3893e98..5db6f618c 100644
--- a/chrome/browser/ui/color/chrome_color_id.h
+++ b/chrome/browser/ui/color/chrome_color_id.h
@@ -306,93 +306,54 @@
   E(kColorTabHoverCardForeground, \
     ThemeProperties::COLOR_HOVER_CARD_NO_PREVIEW_FOREGROUND) \
   /* The colors used for tab groups in the tabstrip. */ \
-  E(kColorTabGroupTabStripFrameActiveGrey, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY) \
-  E(kColorTabGroupTabStripFrameActiveBlue, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE) \
-  E(kColorTabGroupTabStripFrameActiveRed, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED) \
-  E(kColorTabGroupTabStripFrameActiveYellow, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW) \
-  E(kColorTabGroupTabStripFrameActiveGreen, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN) \
-  E(kColorTabGroupTabStripFrameActivePink, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK) \
-  E(kColorTabGroupTabStripFrameActivePurple, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE) \
-  E(kColorTabGroupTabStripFrameActiveCyan, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN) \
-  E(kColorTabGroupTabStripFrameActiveOrange, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE) \
-  E(kColorTabGroupTabStripFrameInactiveGrey, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY) \
-  E(kColorTabGroupTabStripFrameInactiveBlue, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE) \
-  E(kColorTabGroupTabStripFrameInactiveRed, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED) \
-  E(kColorTabGroupTabStripFrameInactiveYellow, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW) \
-  E(kColorTabGroupTabStripFrameInactiveGreen, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN) \
-  E(kColorTabGroupTabStripFrameInactivePink, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK) \
-  E(kColorTabGroupTabStripFrameInactivePurple, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE) \
-  E(kColorTabGroupTabStripFrameInactiveCyan, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN) \
-  E(kColorTabGroupTabStripFrameInactiveOrange, \
-    ThemeProperties::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveGrey) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveBlue) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveRed) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveYellow) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveGreen) \
+  E_CPONLY(kColorTabGroupTabStripFrameActivePink) \
+  E_CPONLY(kColorTabGroupTabStripFrameActivePurple) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveCyan) \
+  E_CPONLY(kColorTabGroupTabStripFrameActiveOrange) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveGrey) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveBlue) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveRed) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveYellow) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveGreen) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactivePink) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactivePurple) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveCyan) \
+  E_CPONLY(kColorTabGroupTabStripFrameInactiveOrange) \
   /* The colors used for tab groups in the bubble dialog view. */ \
-  E(kColorTabGroupDialogGrey, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREY) \
-  E(kColorTabGroupDialogBlue, ThemeProperties::COLOR_TAB_GROUP_DIALOG_BLUE) \
-  E(kColorTabGroupDialogRed, ThemeProperties::COLOR_TAB_GROUP_DIALOG_RED) \
-  E(kColorTabGroupDialogYellow, \
-    ThemeProperties::COLOR_TAB_GROUP_DIALOG_YELLOW) \
-  E(kColorTabGroupDialogGreen, ThemeProperties::COLOR_TAB_GROUP_DIALOG_GREEN) \
-  E(kColorTabGroupDialogPink, ThemeProperties::COLOR_TAB_GROUP_DIALOG_PINK) \
-  E(kColorTabGroupDialogPurple, \
-    ThemeProperties::COLOR_TAB_GROUP_DIALOG_PURPLE) \
-  E(kColorTabGroupDialogCyan, ThemeProperties::COLOR_TAB_GROUP_DIALOG_CYAN) \
-  E(kColorTabGroupDialogOrange, \
-    ThemeProperties::COLOR_TAB_GROUP_DIALOG_ORANGE) \
+  E_CPONLY(kColorTabGroupDialogGrey) \
+  E_CPONLY(kColorTabGroupDialogBlue) \
+  E_CPONLY(kColorTabGroupDialogRed) \
+  E_CPONLY(kColorTabGroupDialogYellow) \
+  E_CPONLY(kColorTabGroupDialogGreen) \
+  E_CPONLY(kColorTabGroupDialogPink) \
+  E_CPONLY(kColorTabGroupDialogPurple) \
+  E_CPONLY(kColorTabGroupDialogCyan) \
+  E_CPONLY(kColorTabGroupDialogOrange) \
   /* The colors used for tab groups in the context submenu. */ \
-  E(kColorTabGroupContextMenuBlue, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE) \
-  E(kColorTabGroupContextMenuCyan, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN) \
-  E(kColorTabGroupContextMenuGreen, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN) \
-  E(kColorTabGroupContextMenuGrey, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_GREY) \
-  E(kColorTabGroupContextMenuOrange, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE) \
-  E(kColorTabGroupContextMenuPink, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PINK) \
-  E(kColorTabGroupContextMenuPurple, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE) \
-  E(kColorTabGroupContextMenuRed, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_RED) \
-  E(kColorTabGroupContextMenuYellow, \
-    ThemeProperties::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW) \
+  E_CPONLY(kColorTabGroupContextMenuBlue) \
+  E_CPONLY(kColorTabGroupContextMenuCyan) \
+  E_CPONLY(kColorTabGroupContextMenuGreen) \
+  E_CPONLY(kColorTabGroupContextMenuGrey) \
+  E_CPONLY(kColorTabGroupContextMenuOrange) \
+  E_CPONLY(kColorTabGroupContextMenuPink) \
+  E_CPONLY(kColorTabGroupContextMenuPurple) \
+  E_CPONLY(kColorTabGroupContextMenuRed) \
+  E_CPONLY(kColorTabGroupContextMenuYellow) \
   /* The colors used for saved tab group chips on the bookmark bar. */ \
-  E(kColorTabGroupBookmarkBarGrey, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY) \
-  E(kColorTabGroupBookmarkBarBlue, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE) \
-  E(kColorTabGroupBookmarkBarRed, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_RED) \
-  E(kColorTabGroupBookmarkBarYellow, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW) \
-  E(kColorTabGroupBookmarkBarGreen, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN) \
-  E(kColorTabGroupBookmarkBarPink, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK) \
-  E(kColorTabGroupBookmarkBarPurple, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE) \
-  E(kColorTabGroupBookmarkBarCyan, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN) \
-  E(kColorTabGroupBookmarkBarOrange, \
-    ThemeProperties::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE) \
+  E_CPONLY(kColorTabGroupBookmarkBarGrey) \
+  E_CPONLY(kColorTabGroupBookmarkBarBlue) \
+  E_CPONLY(kColorTabGroupBookmarkBarRed) \
+  E_CPONLY(kColorTabGroupBookmarkBarYellow) \
+  E_CPONLY(kColorTabGroupBookmarkBarGreen) \
+  E_CPONLY(kColorTabGroupBookmarkBarPink) \
+  E_CPONLY(kColorTabGroupBookmarkBarPurple) \
+  E_CPONLY(kColorTabGroupBookmarkBarCyan) \
+  E_CPONLY(kColorTabGroupBookmarkBarOrange) \
   E(kColorTabStrokeFrameActive, \
     ThemeProperties::COLOR_TAB_STROKE_FRAME_ACTIVE) \
   E(kColorTabStrokeFrameInactive, \
diff --git a/chrome/browser/ui/tabs/tab_group_theme.cc b/chrome/browser/ui/tabs/tab_group_theme.cc
index 728572d..5ad43a7 100644
--- a/chrome/browser/ui/tabs/tab_group_theme.cc
+++ b/chrome/browser/ui/tabs/tab_group_theme.cc
@@ -13,37 +13,37 @@
 using TP = ThemeProperties;
 using TabGroupColorId = tab_groups::TabGroupColorId;
 
-int GetTabGroupTabStripColorId(TabGroupColorId group_color_id,
-                               bool active_frame) {
+ui::ColorId GetTabGroupTabStripColorId(TabGroupColorId group_color_id,
+                                       bool active_frame) {
   static constexpr auto group_id_map =
       base::MakeFixedFlatMap<TabGroupColorId, std::array<int, 2>>({
           {TabGroupColorId::kGrey,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREY,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREY}},
+           {kColorTabGroupTabStripFrameInactiveGrey,
+            kColorTabGroupTabStripFrameActiveGrey}},
           {TabGroupColorId::kBlue,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_BLUE,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_BLUE}},
+           {kColorTabGroupTabStripFrameInactiveGrey,
+            kColorTabGroupTabStripFrameActiveBlue}},
           {TabGroupColorId::kRed,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_RED,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_RED}},
+           {kColorTabGroupTabStripFrameInactiveRed,
+            kColorTabGroupTabStripFrameActiveRed}},
           {TabGroupColorId::kYellow,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_YELLOW,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_YELLOW}},
+           {kColorTabGroupTabStripFrameInactiveYellow,
+            kColorTabGroupTabStripFrameActiveYellow}},
           {TabGroupColorId::kGreen,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_GREEN,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_GREEN}},
+           {kColorTabGroupTabStripFrameInactiveGreen,
+            kColorTabGroupTabStripFrameActiveGreen}},
           {TabGroupColorId::kPink,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PINK,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PINK}},
+           {kColorTabGroupTabStripFrameInactivePink,
+            kColorTabGroupTabStripFrameActivePink}},
           {TabGroupColorId::kPurple,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_PURPLE,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_PURPLE}},
+           {kColorTabGroupTabStripFrameInactivePink,
+            kColorTabGroupTabStripFrameActivePurple}},
           {TabGroupColorId::kCyan,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_CYAN,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_CYAN}},
+           {kColorTabGroupTabStripFrameInactiveCyan,
+            kColorTabGroupTabStripFrameActiveCyan}},
           {TabGroupColorId::kOrange,
-           {TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_INACTIVE_ORANGE,
-            TP::COLOR_TAB_GROUP_TABSTRIP_FRAME_ACTIVE_ORANGE}},
+           {kColorTabGroupTabStripFrameInactiveOrange,
+            kColorTabGroupTabStripFrameActiveOrange}},
       });
 
   return group_id_map.at(group_color_id)[active_frame];
@@ -85,18 +85,18 @@
   return group_id_map.at(group_color_id)[active_frame];
 }
 
-int GetTabGroupDialogColorId(TabGroupColorId group_color_id) {
+ui::ColorId GetTabGroupDialogColorId(TabGroupColorId group_color_id) {
   static constexpr auto group_id_map =
       base::MakeFixedFlatMap<TabGroupColorId, int>({
-          {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_DIALOG_GREY},
-          {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_DIALOG_BLUE},
-          {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_DIALOG_RED},
-          {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_DIALOG_YELLOW},
-          {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_DIALOG_GREEN},
-          {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_DIALOG_PINK},
-          {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_DIALOG_PURPLE},
-          {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_DIALOG_CYAN},
-          {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_DIALOG_ORANGE},
+          {TabGroupColorId::kGrey, kColorTabGroupDialogGrey},
+          {TabGroupColorId::kBlue, kColorTabGroupDialogBlue},
+          {TabGroupColorId::kRed, kColorTabGroupDialogRed},
+          {TabGroupColorId::kYellow, kColorTabGroupDialogYellow},
+          {TabGroupColorId::kGreen, kColorTabGroupDialogGreen},
+          {TabGroupColorId::kPink, kColorTabGroupDialogPink},
+          {TabGroupColorId::kPurple, kColorTabGroupDialogPurple},
+          {TabGroupColorId::kCyan, kColorTabGroupDialogCyan},
+          {TabGroupColorId::kOrange, kColorTabGroupDialogOrange},
       });
 
   return group_id_map.at(group_color_id);
@@ -119,35 +119,19 @@
   return group_id_map.at(group_color_id);
 }
 
-int GetTabGroupContextMenuColorIdDeprecated(TabGroupColorId group_color_id) {
+ui::ColorId GetTabGroupBookmarkColorId(
+    tab_groups::TabGroupColorId group_color_id) {
   static constexpr auto group_id_map =
       base::MakeFixedFlatMap<TabGroupColorId, int>({
-          {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREY},
-          {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_CONTEXT_MENU_BLUE},
-          {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_CONTEXT_MENU_RED},
-          {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_CONTEXT_MENU_YELLOW},
-          {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_CONTEXT_MENU_GREEN},
-          {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PINK},
-          {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_CONTEXT_MENU_PURPLE},
-          {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_CONTEXT_MENU_CYAN},
-          {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_CONTEXT_MENU_ORANGE},
-      });
-
-  return group_id_map.at(group_color_id);
-}
-
-int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id) {
-  static constexpr auto group_id_map =
-      base::MakeFixedFlatMap<TabGroupColorId, int>({
-          {TabGroupColorId::kGrey, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREY},
-          {TabGroupColorId::kBlue, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_BLUE},
-          {TabGroupColorId::kRed, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_RED},
-          {TabGroupColorId::kYellow, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_YELLOW},
-          {TabGroupColorId::kGreen, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_GREEN},
-          {TabGroupColorId::kPink, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PINK},
-          {TabGroupColorId::kPurple, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_PURPLE},
-          {TabGroupColorId::kCyan, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_CYAN},
-          {TabGroupColorId::kOrange, TP::COLOR_TAB_GROUP_BOOKMARK_BAR_ORANGE},
+          {TabGroupColorId::kGrey, kColorTabGroupBookmarkBarGrey},
+          {TabGroupColorId::kBlue, kColorTabGroupBookmarkBarBlue},
+          {TabGroupColorId::kRed, kColorTabGroupBookmarkBarRed},
+          {TabGroupColorId::kYellow, kColorTabGroupBookmarkBarYellow},
+          {TabGroupColorId::kGreen, kColorTabGroupBookmarkBarGreen},
+          {TabGroupColorId::kPink, kColorTabGroupBookmarkBarPink},
+          {TabGroupColorId::kPurple, kColorTabGroupBookmarkBarPurple},
+          {TabGroupColorId::kCyan, kColorTabGroupBookmarkBarCyan},
+          {TabGroupColorId::kOrange, kColorTabGroupBookmarkBarOrange},
       });
 
   return group_id_map.at(group_color_id);
diff --git a/chrome/browser/ui/tabs/tab_group_theme.h b/chrome/browser/ui/tabs/tab_group_theme.h
index be5a1ed..2c56bd5 100644
--- a/chrome/browser/ui/tabs/tab_group_theme.h
+++ b/chrome/browser/ui/tabs/tab_group_theme.h
@@ -8,23 +8,21 @@
 #include "components/tab_groups/tab_group_color.h"
 #include "ui/color/color_id.h"
 
-int GetTabGroupTabStripColorId(tab_groups::TabGroupColorId group_color_id,
-                               bool active_frame);
+ui::ColorId GetTabGroupTabStripColorId(
+    tab_groups::TabGroupColorId group_color_id,
+    bool active_frame);
 
 ui::ColorId GetThumbnailTabStripTabGroupColorId(
     tab_groups::TabGroupColorId group_color_id,
     bool active_frame);
 
-int GetTabGroupDialogColorId(tab_groups::TabGroupColorId group_color_id);
+ui::ColorId GetTabGroupDialogColorId(
+    tab_groups::TabGroupColorId group_color_id);
 
 ui::ColorId GetTabGroupContextMenuColorId(
     tab_groups::TabGroupColorId group_color_id);
 
-// TODO(crbug.com/1292029): Remove this function which returns color id for
-// ThemeService, not for ColorProvider.
-int GetTabGroupContextMenuColorIdDeprecated(
+ui::ColorId GetTabGroupBookmarkColorId(
     tab_groups::TabGroupColorId group_color_id);
 
-int GetTabGroupBookmarkColorId(tab_groups::TabGroupColorId group_color_id);
-
 #endif  // CHROME_BROWSER_UI_TABS_TAB_GROUP_THEME_H_
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc
index 8003938..08a8b7a 100644
--- a/chrome/browser/ui/views/accelerator_table.cc
+++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -201,7 +201,9 @@
     {ui::VKEY_LEFT, ui::EF_ALT_DOWN, IDC_BACK},
     {ui::VKEY_LEFT, ui::EF_ALTGR_DOWN, IDC_BACK},
 #if BUILDFLAG(ENABLE_PRINTING)
-    {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT},
+    {ui::VKEY_P, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
+     IDC_BASIC_PRINT_DEPRECATED},
+    {ui::VKEY_P, ui::EF_ALT_DOWN | ui::EF_CONTROL_DOWN, IDC_BASIC_PRINT},
 #endif  // ENABLE_PRINTING
     {ui::VKEY_I, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_DEV_TOOLS},
     {ui::VKEY_J, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN,
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc
index 0d5cf2e..1acd818e 100644
--- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc
+++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.cc
@@ -121,16 +121,16 @@
 }
 
 void SavedTabGroupButton::OnPaintBackground(gfx::Canvas* canvas) {
-  const ui::ThemeProvider* const tp = GetThemeProvider();
+  const ui::ColorProvider* const cp = GetColorProvider();
   gfx::PointF center_point_f = gfx::PointF(width() / 2, height() / 2);
   gfx::RectF rect_f = gfx::RectF(width(), height());
   rect_f.Inset(1.0f);
 
   // Relies on logic in theme_helper.cc to determine dark/light palette.
   SkColor background_color =
-      tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_));
+      cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_));
   SkColor text_and_outline_color =
-      tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_));
+      cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_));
   SetEnabledTextColors(text_and_outline_color);
 
   // Draw background.
@@ -176,11 +176,11 @@
 
   // We don't always have a theme provider (ui tests, for example).
   SkColor text_color = gfx::kPlaceholderColor;
-  const ui::ThemeProvider* const tp = GetThemeProvider();
-  if (tp) {
+  const ui::ColorProvider* const cp = GetColorProvider();
+  if (cp) {
     SkColor background_color =
-        tp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_));
-    text_color = tp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_));
+        cp->GetColor(GetTabGroupBookmarkColorId(tab_group_color_id_));
+    text_color = cp->GetColor(GetTabGroupDialogColorId(tab_group_color_id_));
     text_color = color_utils::PickGoogleColor(
         text_color, background_color,
         color_utils::kMinimumReadableContrastRatio);
diff --git a/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc b/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc
index bde82fc..38e8ab09b 100644
--- a/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc
+++ b/chrome/browser/ui/views/extensions/extensions_request_access_button_hover_card.cc
@@ -59,8 +59,17 @@
 
   auto bubble = std::make_unique<views::BubbleDialogModelHost>(
       dialog_builder.Build(), anchor_view, views::BubbleBorder::TOP_RIGHT);
+  // Hover card should not become active window when hovering over request
+  // button in an inactive window. Setting this to false creates the need to
+  // explicitly hide the hovercard.
+  bubble->SetCanActivate(false);
   request_access_bubble = bubble.get();
-  views::BubbleDialogDelegate::CreateBubble(std::move(bubble))->Show();
+
+  auto* widget = views::BubbleDialogDelegate::CreateBubble(std::move(bubble));
+  // Ensure the hover card Widget assumes the highest z-order to avoid occlusion
+  // by other secondary UI Widgets
+  widget->StackAtTop();
+  widget->Show();
 }
 
 // static
diff --git a/chrome/browser/ui/views/tabs/color_picker_view.cc b/chrome/browser/ui/views/tabs/color_picker_view.cc
index 7ea92f03..75a4f024 100644
--- a/chrome/browser/ui/views/tabs/color_picker_view.cc
+++ b/chrome/browser/ui/views/tabs/color_picker_view.cc
@@ -150,7 +150,7 @@
     DCHECK_EQ(bounds.width(), bounds.height());
 
     const SkColor color =
-        GetThemeProvider()->GetColor(GetTabGroupDialogColorId(color_id_));
+        GetColorProvider()->GetColor(GetTabGroupDialogColorId(color_id_));
 
     cc::PaintFlags flags;
     flags.setStyle(cc::PaintFlags::kFill_Style);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index 5e00e54..995bf8c 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1601,7 +1601,7 @@
 
 SkColor TabStrip::GetPaintedGroupColor(
     const tab_groups::TabGroupColorId& color_id) const {
-  return GetThemeProvider()->GetColor(
+  return GetColorProvider()->GetColor(
       GetTabGroupTabStripColorId(color_id, ShouldPaintAsActiveFrame()));
 }
 
diff --git a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
index 1948075..e830fbb 100644
--- a/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
+++ b/chrome/browser/ui/views/webid/account_selection_bubble_view.cc
@@ -9,7 +9,6 @@
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/accessibility/accessibility_state_utils.h"
 #include "chrome/browser/image_fetcher/image_decoder_impl.h"
-#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/ui/monogram_utils.h"
 #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h"
 #include "chrome/browser/ui/views/hover_button.h"
@@ -19,9 +18,11 @@
 #include "content/public/browser/storage_partition.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkPath.h"
 #include "ui/accessibility/ax_role_properties.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/canvas.h"
 #include "ui/gfx/image/canvas_image_source.h"
 #include "ui/gfx/image/image_skia_operations.h"
 #include "ui/views/accessibility/view_accessibility.h"
@@ -95,6 +96,11 @@
   LetterAvatarImageSkiaSource(const std::u16string& letter, int size)
       : gfx::CanvasImageSource(gfx::Size(size, size)), letter_(letter) {}
 
+  LetterAvatarImageSkiaSource(const LetterAvatarImageSkiaSource&) = delete;
+  LetterAvatarImageSkiaSource& operator=(const LetterAvatarImageSkiaSource&) =
+      delete;
+  ~LetterAvatarImageSkiaSource() override = default;
+
   void Draw(gfx::Canvas* canvas) override {
     monogram::DrawMonogramInCanvas(canvas, size().width(), size().width(),
                                    letter_, SK_ColorWHITE, SK_ColorGRAY);
@@ -104,6 +110,48 @@
   const std::u16string letter_;
 };
 
+// A CanvasImageSource that draws a circle cropped avatar.
+class AvatarImageSkiaSource : public gfx::CanvasImageSource {
+ public:
+  AvatarImageSkiaSource(gfx::ImageSkia avatar, int canvas_edge_size)
+      : gfx::CanvasImageSource(gfx::Size(canvas_edge_size, canvas_edge_size)) {
+    // Resize `avatar` so that it completely fills the canvas.
+    float height_ratio = ((float)avatar.height() / (float)avatar.width());
+    int scaled_width = canvas_edge_size;
+    int scaled_height = canvas_edge_size;
+    if (height_ratio >= 1.0f)
+      scaled_height = floor(canvas_edge_size * height_ratio);
+    else
+      scaled_width = floor(canvas_edge_size / height_ratio);
+    avatar_ = gfx::ImageSkiaOperations::CreateResizedImage(
+        avatar, skia::ImageOperations::RESIZE_BEST,
+        gfx::Size(scaled_width, scaled_height));
+  }
+
+  AvatarImageSkiaSource(const AvatarImageSkiaSource&) = delete;
+  AvatarImageSkiaSource& operator=(const AvatarImageSkiaSource&) = delete;
+  ~AvatarImageSkiaSource() override = default;
+
+  // CanvasImageSource override:
+  void Draw(gfx::Canvas* canvas) override {
+    int canvas_edge_size = size().width();
+
+    // Center the avatar in the canvas.
+    int x = (canvas_edge_size - avatar_.width()) / 2;
+    int y = (canvas_edge_size - avatar_.height()) / 2;
+
+    SkPath circular_mask;
+    circular_mask.addCircle(SkIntToScalar(canvas_edge_size / 2),
+                            SkIntToScalar(canvas_edge_size / 2),
+                            SkIntToScalar(canvas_edge_size / 2));
+    canvas->ClipPath(circular_mask, true);
+    canvas->DrawImageInt(avatar_, x, y);
+  }
+
+ private:
+  gfx::ImageSkia avatar_;
+};
+
 void SendAccessibilityEvent(views::Widget* widget,
                             std::u16string announcement) {
   if (!widget)
@@ -428,17 +476,16 @@
     const std::u16string& account_name,
     const gfx::Image& image,
     const image_fetcher::RequestMetadata& metadata) {
-  ui::ImageModel avatar;
+  gfx::ImageSkia avatar;
   if (image.IsEmpty()) {
     std::u16string letter = account_name;
     if (letter.length() > 0)
       letter = base::i18n::ToUpper(account_name.substr(0, 1));
-    avatar = ui::ImageModel::FromImageSkia(
-        gfx::CanvasImageSource::MakeImageSkia<LetterAvatarImageSkiaSource>(
-            letter, kDesiredAvatarSize));
+    avatar = gfx::CanvasImageSource::MakeImageSkia<LetterAvatarImageSkiaSource>(
+        letter, kDesiredAvatarSize);
   } else {
-    avatar = ui::ImageModel::FromImage(profiles::GetSizedAvatarIcon(
-        image, kDesiredAvatarSize, kDesiredAvatarSize, profiles::SHAPE_CIRCLE));
+    avatar = gfx::CanvasImageSource::MakeImageSkia<AvatarImageSkiaSource>(
+        image.AsImageSkia(), kDesiredAvatarSize);
   }
   image_view->SetImage(avatar);
 }
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
index 372ddc8..627acbe 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.cc
@@ -189,14 +189,15 @@
   return app_id;
 }
 
-Browser* LaunchWebAppBrowser(Profile* profile, const AppId& app_id) {
+Browser* LaunchWebAppBrowser(Profile* profile,
+                             const AppId& app_id,
+                             WindowOpenDisposition disposition) {
   content::WebContents* web_contents =
       apps::AppServiceProxyFactory::GetForProfile(profile)
           ->BrowserAppLauncher()
           ->LaunchAppWithParamsForTesting(apps::AppLaunchParams(
               app_id, apps::mojom::LaunchContainer::kLaunchContainerWindow,
-              WindowOpenDisposition::CURRENT_TAB,
-              apps::mojom::LaunchSource::kFromTest));
+              disposition, apps::mojom::LaunchSource::kFromTest));
   EXPECT_TRUE(web_contents);
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
   EXPECT_TRUE(AppBrowserController::IsForWebApp(browser, app_id));
@@ -204,11 +205,14 @@
 }
 
 // Launches the app, waits for the app url to load.
-Browser* LaunchWebAppBrowserAndWait(Profile* profile, const AppId& app_id) {
+Browser* LaunchWebAppBrowserAndWait(Profile* profile,
+                                    const AppId& app_id,
+                                    WindowOpenDisposition disposition) {
   ui_test_utils::UrlLoadObserver url_observer(
       WebAppProvider::GetForTest(profile)->registrar().GetAppLaunchUrl(app_id),
       content::NotificationService::AllSources());
-  Browser* const app_browser = LaunchWebAppBrowser(profile, app_id);
+  Browser* const app_browser =
+      LaunchWebAppBrowser(profile, app_id, disposition);
   url_observer.Wait();
   return app_browser;
 }
diff --git a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
index ce6eaf6..7efe369 100644
--- a/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
+++ b/chrome/browser/ui/web_applications/test/web_app_browsertest_util.h
@@ -17,6 +17,7 @@
 #include "chrome/browser/web_applications/web_app_install_manager.h"
 #include "chrome/browser/web_applications/web_app_install_manager_observer.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/window_open_disposition.h"
 
 class Browser;
 class GURL;
@@ -48,11 +49,18 @@
 // Navigates to |app_url|, verifies WebApp installability, and installs app.
 AppId InstallWebAppFromManifest(Browser* browser, const GURL& app_url);
 
-// Launches a new app window for |app| in |profile|.
-Browser* LaunchWebAppBrowser(Profile*, const AppId&);
+// Launches a new app window for |app| in |profile| with specified
+// |disposition|.
+Browser* LaunchWebAppBrowser(
+    Profile*,
+    const AppId&,
+    WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB);
 
 // Launches the app, waits for the app url to load.
-Browser* LaunchWebAppBrowserAndWait(Profile*, const AppId&);
+Browser* LaunchWebAppBrowserAndWait(
+    Profile*,
+    const AppId&,
+    WindowOpenDisposition disposition = WindowOpenDisposition::CURRENT_TAB);
 
 // Launches a new tab for |app| in |profile|.
 Browser* LaunchBrowserForWebAppInTab(Profile*, const AppId&);
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index b4cd7581..7efefed 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -837,6 +837,30 @@
 
   EXPECT_TRUE(restored_browser->is_type_app());
 }
+
+// Tests that app popup windows are correctly restored.
+IN_PROC_BROWSER_TEST_F(WebAppTabRestoreBrowserTest, RestoreAppPopupWindow) {
+  const GURL app_url = GetSecureAppURL();
+  const AppId app_id = InstallPWA(app_url);
+  Browser* const app_browser = web_app::LaunchWebAppBrowserAndWait(
+      profile(), app_id, WindowOpenDisposition::NEW_POPUP);
+
+  ASSERT_TRUE(app_browser->is_type_app_popup());
+  app_browser->window()->Close();
+
+  content::WebContentsAddedObserver new_contents_observer;
+
+  sessions::TabRestoreService* const service =
+      TabRestoreServiceFactory::GetForProfile(profile());
+  service->RestoreMostRecentEntry(nullptr);
+
+  content::WebContents* const restored_web_contents =
+      new_contents_observer.GetWebContents();
+  Browser* const restored_browser =
+      chrome::FindBrowserWithWebContents(restored_web_contents);
+
+  EXPECT_TRUE(restored_browser->is_type_app_popup());
+}
 #endif  // !BUILDFLAG(IS_CHROMEOS_LACROS)
 
 // Test navigating to an out of scope url on the same origin causes the url
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 70a13e9c..0ca5602 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -93,7 +93,7 @@
 #if BUILDFLAG(IS_MAC)
 const char16_t kBasicPrintShortcut[] = u"\u0028\u21e7\u2318\u0050\u0029";
 #elif !BUILDFLAG(IS_CHROMEOS)
-const char16_t kBasicPrintShortcut[] = u"(Ctrl+Shift+P)";
+const char16_t kBasicPrintShortcut[] = u"(Ctrl+Alt+P)";
 #endif
 
 constexpr char kInvalidArgsForDidStartPreview[] =
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 107c3f52..d58ec07 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1654700057-293efac59be5a3cdb9b1198d0d15440ca2bd2da2.profdata
+chrome-win32-main-1654711203-dd1524393825bce89244c153ae7bb5d820cccb69.profdata
diff --git a/chrome/common/extensions/api/file_browser_handler_internal.json b/chrome/common/extensions/api/file_browser_handler_internal.json
index cf2585a..472e3eb 100644
--- a/chrome/common/extensions/api/file_browser_handler_internal.json
+++ b/chrome/common/extensions/api/file_browser_handler_internal.json
@@ -28,6 +28,25 @@
             "type": "boolean"
           }
         }
+      },
+      {
+        "id": "FileEntryInfoForGetFile",
+        "type": "object",
+        "description": "Information needed to build a file entry using DirectoryEntry.getFile() that will be returned through the API.",
+        "properties": {
+          "fileSystemId": {
+            "type": "string"
+          },
+          "baseName": {
+            "type": "string"
+          },
+          "entryId": {
+            "type": "string"
+          },
+          "isDirectory": {
+            "type": "boolean"
+          }
+        }
       }
     ],
 
@@ -72,6 +91,11 @@
                   "$ref": "FileEntryInfo",
                   "optional": true,
                   "description": "Selected file entry."
+                },
+                "entryForGetFile": {
+                  "$ref": "FileEntryInfoForGetFile",
+                  "optional": true,
+                  "description": "Selected file entry for DirectoryEngry.getFile() consumption."
                 }
               }
             }
diff --git a/chrome/common/extensions/api/wm_desks_private.idl b/chrome/common/extensions/api/wm_desks_private.idl
index e8f388b..3c9f227 100644
--- a/chrome/common/extensions/api/wm_desks_private.idl
+++ b/chrome/common/extensions/api/wm_desks_private.idl
@@ -10,6 +10,8 @@
     // The unique id for a desk template. Used internally to identify a desk
     // template.
     DOMString templateUuid;
+
+    // User readable name of the desk template.
     DOMString templateName;
   };
 
@@ -19,18 +21,28 @@
     boolean combineDesks;
   };
 
-   dictionary Desk {
+  dictionary Desk {
     // Unique ID for a desk.
     DOMString deskUuid;
+
     // User readable name of the desk.
     DOMString deskName;
   };
 
+  // Launch desk options
+  dictionary LaunchOptions {
+    // Unique identifier for a template
+    DOMString? templateUuid;
+
+    // User readable name of the desk
+    DOMString? deskName;
+};
+
   callback CaptureDeskAndSaveTemplateCallback =
       void (DeskTemplate deskTemplate);
   callback GetSavedDeskTemplatesCallback =
       void (DeskTemplate[] deskTemplates);
-  callback LaunchDeskTemplateCallback = void (DOMString deskId);
+  callback DeskIdCallback = void (DOMString deskId);
   callback VoidCallback = void ();
   callback GetDeskTemplateJsonCallback = void (DOMString templateJson);
   callback GetAllDesksCallback = void (Desk[] desks);
@@ -61,12 +73,11 @@
     static void deleteDeskTemplate(DOMString templateUuid,
                                    VoidCallback callback);
 
-    // Launches the desk template with |templateUuid| as a new desk.
-    // |templateId| should be the unique id for an existing desk template. If
-    // no such id can be found or a new desk can't be created, an error will be
-    // returned.
-    static void launchDeskTemplate(DOMString templateUuid,
-                                   LaunchDeskTemplateCallback callback);
+    // Launches a desk, if `templateUuid` is present in the options, launches a desk
+    // template, otherwise launches an empty desk. If `deskName` is present in the options,
+    // using provided name as desk name, otherwise launches with auto generated name.
+    static void launchDesk(LaunchOptions launchOptions,
+                           DeskIdCallback callback);
 
     // Gets the template associated with the templateUuid and returns its JSON
     // representation.  Returns an error if either the template could not be
diff --git a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js
index 1e8859bf..d73b306 100644
--- a/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js
+++ b/chrome/renderer/resources/extensions/file_browser_handler_custom_bindings.js
@@ -12,9 +12,20 @@
 const fileBrowserHandlerInternal = getInternalApi('fileBrowserHandlerInternal');
 const GetIsolatedFileSystem = fileSystemHelpers.GetIsolatedFileSystem;
 
-// Using Promise-like interface: We're avoiding Promise for safety, and $Promise
-// does not support the desired feature (Promise.allSettled()).
-function GetFileEntry(resolve, reject, item) {
+/**
+ * Adapter to get a FileEntry or DirectoryEntry from |item| passed from API
+ * callback, via calls to GetExternalFileEntry() or get{Directory,File}().
+ * Ideally we'd use Promise.allSettled() to process multiple files, but since
+ * $Promise.allSettled() does not exist, so callbacks are used instead.
+ * @param {function(!Entry): void} resolve Receiver for resulting Entry.
+ * @param {function(string): void} reject Receiver for error message.
+ * @param {boolean} canCreate For getFile() flow only: Whether to grant
+ *   permission to create file if it's missing. Side effect: The file gets
+ *   created if missing.
+ * @param {!Object} item Key-value pair passed from API callback, containing
+ *   data for GetExternalFileEntry() or get{Directory,File}() flows.
+ */
+function GetFileEntry(resolve, reject, canCreate, item) {
   if (item.hasOwnProperty('fileSystemName')) {
     // Legacy flow for Ash. Errors (such as nonexistent file) are not detected
     // here. These only arise downstream when the resulting Entry gets used.
@@ -31,12 +42,15 @@
         reject(err.message);
       });
     } else {
-      fs.root.getFile(item.baseName, {}, (fileEntry) => {
-        entryIdManager.registerEntry(item.entryId, fileEntry);
-        resolve(fileEntry);
-      }, (err) => {
-        reject(err.message);
-      });
+      fs.root.getFile(
+          item.baseName, canCreate ? {create: true} : {},
+          (fileEntry) => {
+            entryIdManager.registerEntry(item.entryId, fileEntry);
+            resolve(fileEntry);
+          },
+          (err) => {
+            reject(err.message);
+          });
     }
   } else {
     reject('Unknown file entry object.');
@@ -74,7 +88,9 @@
     if (--barrier === 0) onFinish();
   };
   for (let i = 0; i < fileList.length; ++i) {
-    GetFileEntry(onResolve.bind(null, i), onReject, fileList[i]);
+    GetFileEntry(
+        onResolve.bind(null, i), onReject,
+        /*canCreate*/ false, /*item*/ fileList[i]);
   }
 });
 
@@ -86,13 +102,25 @@
     function internalCallback(externalCallback, internalResult) {
       if (!externalCallback)
         return;
-      var result = undefined;
+      let result = undefined;
       if (internalResult) {
         result = { success: internalResult.success, entry: null };
-        if (internalResult.success)
-          result.entry = GetExternalFileEntry(internalResult.entry);
+        if (internalResult.success) {
+          GetFileEntry(
+              (fileEntry) => {
+                result.entry = fileEntry;
+                externalCallback(result);
+              },
+              (message) => {
+                result.success = false;
+                result.entry = null;
+                externalCallback(result);
+              },
+              /*canCreate*/ true,
+              /*item*/ internalResult.entry || internalResult.entryForGetFile);
+          return;
+        }
       }
-
       externalCallback(result);
     }
 
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
index 44c7e52..94bacf6 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_browsertest.cc
@@ -59,8 +59,7 @@
         page_link_domain_phishing_(features::kPageLinkDomain +
                                    std::string("phishing.com")),
         page_term_login_(features::kPageTerm + std::string("login")),
-        page_text_(u"login"),
-        phishy_score_(PhishingClassifier::kInvalidScore) {}
+        page_text_(u"login") {}
 
   void SetUp() override {
     ChromeRenderViewTest::SetUp();
@@ -183,6 +182,7 @@
     csd_model_builder.add_max_shingles_per_page(100);
     csd_model_builder.add_shingle_size(3);
     csd_model_builder.add_tflite_metadata(tflite_metadata_flat);
+    csd_model_builder.add_dom_model_version(123);
 
     builder.Finish(csd_model_builder.Finish());
     std::string model_str(reinterpret_cast<char*>(builder.GetBufferPointer()),
@@ -240,6 +240,7 @@
     model.set_max_words_per_term(1);
     model.set_max_shingles_per_page(100);
     model.set_shingle_size(3);
+    model.set_dom_model_version(123);
 
     base::File tflite_model;
     if (use_tflite) {
@@ -306,14 +307,11 @@
 
   // Completion callback for classification.
   void ClassificationFinished(const ClientPhishingRequest& verdict) {
-    phishy_score_ = verdict.client_score();
+    verdict_ = verdict;
     for (int i = 0; i < verdict.feature_map_size(); ++i) {
       feature_map_.AddRealFeature(verdict.feature_map(i).name(),
                                   verdict.feature_map(i).value());
     }
-    is_phishing_ = verdict.is_phishing();
-    is_dom_match_ = verdict.is_dom_match();
-
     run_loop_.Quit();
   }
 
@@ -339,10 +337,8 @@
   std::u16string page_text_;
 
   // Outputs of phishing classifier.
+  ClientPhishingRequest verdict_;
   FeatureMap feature_map_;
-  float phishy_score_;
-  bool is_phishing_;
-  bool is_dom_match_;
 
   // A DiscardableMemoryAllocator is needed for certain Skia operations.
   base::TestDiscardableMemoryAllocator test_allocator_;
@@ -360,8 +356,8 @@
               AllOf(Contains(Pair(url_tld_token_net_, 1.0)),
                     Contains(Pair(page_link_domain_phishing_, 1.0)),
                     Contains(Pair(page_term_login_, 1.0))));
-  EXPECT_FLOAT_EQ(0.5, phishy_score_);
-  EXPECT_TRUE(is_phishing_);
+  EXPECT_FLOAT_EQ(0.5, verdict_.client_score());
+  EXPECT_TRUE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, TestClassificationOfPhishingDotComHttps) {
@@ -377,8 +373,8 @@
               AllOf(Contains(Pair(url_tld_token_net_, 1.0)),
                     Contains(Pair(page_link_domain_phishing_, 1.0)),
                     Contains(Pair(page_term_login_, 1.0))));
-  EXPECT_FLOAT_EQ(0.5, phishy_score_);
-  EXPECT_TRUE(is_phishing_);
+  EXPECT_FLOAT_EQ(0.5, verdict_.client_score());
+  EXPECT_TRUE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, TestClassificationOfSafeDotComHttp) {
@@ -392,9 +388,9 @@
                     Contains(Pair(page_term_login_, 1.0))));
   EXPECT_THAT(feature_map_.features(),
               Not(Contains(Pair(page_link_domain_phishing_, 1.0))));
-  EXPECT_GE(phishy_score_, 0.0);
-  EXPECT_LT(phishy_score_, 0.5);
-  EXPECT_FALSE(is_phishing_);
+  EXPECT_GE(verdict_.client_score(), 0.0);
+  EXPECT_LT(verdict_.client_score(), 0.5);
+  EXPECT_FALSE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, TestClassificationOfSafeDotComHttps) {
@@ -409,9 +405,9 @@
                     Contains(Pair(page_term_login_, 1.0))));
   EXPECT_THAT(feature_map_.features(),
               Not(Contains(Pair(page_link_domain_phishing_, 1.0))));
-  EXPECT_GE(phishy_score_, 0.0);
-  EXPECT_LT(phishy_score_, 0.5);
-  EXPECT_FALSE(is_phishing_);
+  EXPECT_GE(verdict_.client_score(), 0.0);
+  EXPECT_LT(verdict_.client_score(), 0.5);
+  EXPECT_FALSE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, TestClassificationWhenNoTld) {
@@ -420,8 +416,8 @@
   RunPhishingClassifier(&page_text_);
 
   EXPECT_EQ(0U, feature_map_.features().size());
-  EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_);
-  EXPECT_FALSE(is_phishing_);
+  EXPECT_EQ(PhishingClassifier::kInvalidScore, verdict_.client_score());
+  EXPECT_FALSE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, TestClassificationWhenSchemeNotSupported) {
@@ -431,8 +427,8 @@
   RunPhishingClassifier(&page_text_);
 
   EXPECT_EQ(0U, feature_map_.features().size());
-  EXPECT_EQ(PhishingClassifier::kInvalidScore, phishy_score_);
-  EXPECT_FALSE(is_phishing_);
+  EXPECT_EQ(PhishingClassifier::kInvalidScore, verdict_.client_score());
+  EXPECT_FALSE(verdict_.is_phishing());
 }
 
 TEST_P(PhishingClassifierTest, DisableDetection) {
@@ -448,9 +444,9 @@
       "<html><body><a href=\"http://phishing.com/\">login</a></body></html>");
   RunPhishingClassifier(&page_text_);
 
-  EXPECT_NE(PhishingClassifier::kInvalidScore, phishy_score_);
-  EXPECT_TRUE(is_phishing_);
-  EXPECT_TRUE(is_dom_match_);
+  EXPECT_NE(PhishingClassifier::kInvalidScore, verdict_.client_score());
+  EXPECT_TRUE(verdict_.is_phishing());
+  EXPECT_TRUE(verdict_.is_dom_match());
 }
 
 TEST_P(PhishingClassifierTest, TestSafePagesAreNotDomMatches) {
@@ -458,9 +454,18 @@
            "<html><body><a href=\"http://safe.com/\">login</a></body></html>");
   RunPhishingClassifier(&page_text_);
 
-  EXPECT_NE(PhishingClassifier::kInvalidScore, phishy_score_);
-  EXPECT_FALSE(is_phishing_);
-  EXPECT_FALSE(is_dom_match_);
+  EXPECT_NE(PhishingClassifier::kInvalidScore, verdict_.client_score());
+  EXPECT_FALSE(verdict_.is_phishing());
+  EXPECT_FALSE(verdict_.is_dom_match());
+}
+
+TEST_P(PhishingClassifierTest, TestDomModelVersionPopulated) {
+  LoadHtml(
+      GURL("http://host.net"),
+      "<html><body><a href=\"http://phishing.com/\">login</a></body></html>");
+  RunPhishingClassifier(&page_text_);
+
+  EXPECT_EQ(verdict_.dom_model_version(), 123);
 }
 
 INSTANTIATE_TEST_SUITE_P(CSDModelTypes,
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
index 351a9ff7..df5dfb3 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate_browsertest.cc
@@ -132,6 +132,7 @@
       void(const SkBitmap& bitmap,
            base::OnceCallback<void(std::vector<double>)> callback));
   MOCK_CONST_METHOD0(model_version, int());
+  MOCK_CONST_METHOD0(dom_model_version, int());
   MOCK_CONST_METHOD0(HasVisualTfLiteModel, bool());
   MOCK_CONST_METHOD0(find_page_word_callback,
                      base::RepeatingCallback<bool(uint32_t)>());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index a956dd80..b984d3b2 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6126,6 +6126,7 @@
       "../browser/android/contextualsearch/contextual_search_delegate_unittest.cc",
       "../browser/android/contextualsearch/contextual_search_field_trial_unittest.cc",
       "../browser/android/customtabs/detached_resource_request_unittest.cc",
+      "../browser/android/customtabs/tab_interaction_recorder_android_unittest.cc",
       "../browser/android/explore_sites/block_site_task_unittest.cc",
       "../browser/android/explore_sites/clear_activities_task_unittest.cc",
       "../browser/android/explore_sites/clear_catalog_task_unittest.cc",
diff --git a/chrome/test/android/BUILD.gn b/chrome/test/android/BUILD.gn
index 28b8557..e3dd8b9d 100644
--- a/chrome/test/android/BUILD.gn
+++ b/chrome/test/android/BUILD.gn
@@ -48,7 +48,6 @@
     "//third_party/androidx:androidx_annotation_annotation_java",
     "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
   ]
 }
 
@@ -225,7 +224,7 @@
     ":chrome_java_test_pagecontroller",
     "//base:base_java_test_support",
     "//base:base_junit_test_support",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
   ]
 }
 
@@ -391,11 +390,11 @@
     "//third_party/androidx:androidx_core_core_java",
     "//third_party/androidx:androidx_fragment_fragment_java",
     "//third_party/androidx:androidx_recyclerview_recyclerview_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/blink/public:blink_headers_java",
     "//third_party/blink/public/mojom:mojom_platform_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java",
     "//ui/android:ui_java_test_support",
     "//url:gurl_java",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java
index 0e00cbf..f6ceb0f5b 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/controllers/ntp/SuggestionTileController.java
@@ -6,7 +6,7 @@
 
 import static org.chromium.chrome.test.pagecontroller.utils.Ui2Locators.withText;
 
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObject2;
 
 import org.chromium.chrome.R;
 import org.chromium.chrome.test.pagecontroller.controllers.ElementController;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java
index 22bfcdc..f240225 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2Locator.java
@@ -4,11 +4,10 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.List;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
index 06ee054..9abb345 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorIndexUi2LocatorTest.java
@@ -4,10 +4,10 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java
index aeecaa7d..08850bc 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2Locator.java
@@ -4,11 +4,10 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.List;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
index 33fd1ef..51bb4bb 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/BySelectorUi2LocatorTest.java
@@ -4,10 +4,10 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java
index f5dfb7c5..9649e84 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2Locator.java
@@ -4,11 +4,10 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.Arrays;
 import java.util.List;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
index a9d2cab..dab8038 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/ChildIndexUi2LocatorTest.java
@@ -10,8 +10,8 @@
 
 import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.matchesByDepth;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java
index ff69f5f5..560255b0 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IUi2Locator.java
@@ -4,10 +4,9 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.List;
 
@@ -20,7 +19,7 @@
      *
      * @param device The device to search under.
      * @return       The first node found by the locator, or null if none is found.
-     * @throws       android.support.test.uiautomator.StaleObjectException
+     * @throws       androidx.test.uiautomator.StaleObjectException
      */
     @Nullable
     UiObject2 locateOne(UiDevice device);
@@ -30,7 +29,7 @@
      *
      * @param root The node to search under.
      * @return     The first node found by the locator, or null if none is found.
-     * @throws     android.support.test.uiautomator.StaleObjectException
+     * @throws     androidx.test.uiautomator.StaleObjectException
      */
     @Nullable
     UiObject2 locateOne(UiObject2 root);
@@ -40,7 +39,7 @@
      *
      * @param device The device to search under.
      * @return       All nodes found, or an empty list of none are found.
-     * @throws       android.support.test.uiautomator.StaleObjectException
+     * @throws       androidx.test.uiautomator.StaleObjectException
      */
     List<UiObject2> locateAll(UiDevice device);
 
@@ -49,7 +48,7 @@
      *
      * @param root The node to search under.
      * @return     All nodes found, or an empty list of none are found.
-     * @throws     android.support.test.uiautomator.StaleObjectException
+     * @throws     androidx.test.uiautomator.StaleObjectException
      */
     List<UiObject2> locateAll(UiObject2 root);
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java
index aaaece6e..eccb4c1 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2Locator.java
@@ -4,10 +4,9 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.List;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
index 0893985..c69a986 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/IndexUi2LocatorTest.java
@@ -8,8 +8,8 @@
 
 import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.assertLocatorResults;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java
index 1628fd8..a5d8286 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2Locator.java
@@ -4,10 +4,9 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
-
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import java.util.ArrayList;
 import java.util.Arrays;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
index a9eeafe3..9c5df1f4 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/PathUi2LocatorTest.java
@@ -8,8 +8,8 @@
 
 import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.assertLocatorResults;
 
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.Before;
 import org.junit.FixMethodOrder;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java
index 642bcd7..c7427164 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/TestUtils.java
@@ -7,9 +7,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Mockito.when;
 
-import android.support.test.uiautomator.BySelector;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.mockito.ArgumentMatcher;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java
index 22389b5..3eff745 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2Locators.java
@@ -6,11 +6,11 @@
 
 import android.content.res.Resources;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.By;
 
 import androidx.annotation.IdRes;
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
+import androidx.test.uiautomator.By;
 
 import java.util.regex.Pattern;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
index e781e3b..49bcbfb 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/Ui2LocatorsTest.java
@@ -13,8 +13,9 @@
 import static org.chromium.chrome.test.pagecontroller.utils.TestUtils.matchesByField;
 
 import android.content.res.Resources;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
+
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java
index 59b6ff1..9985997 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiAutomatorUtils.java
@@ -13,10 +13,10 @@
 import android.os.Process;
 import android.os.RemoteException;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
 
 import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.chromium.base.Log;
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java
index 02676227..43bcbffd 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocationException.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.test.pagecontroller.utils;
 
-import android.support.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObject2;
 
 /**
  * Exception class that represents an unexpected failure when trying to find
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java
index 8dc5b42..d0358e3 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/utils/UiLocatorHelper.java
@@ -5,12 +5,12 @@
 package org.chromium.chrome.test.pagecontroller.utils;
 
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.StaleObjectException;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.test.uiautomator.StaleObjectException;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.chromium.base.test.util.TimeoutTimer;
 
diff --git a/chrome/test/base/chromeos/ash_browser_test_starter.cc b/chrome/test/base/chromeos/ash_browser_test_starter.cc
index d631d72f..e24c3970 100644
--- a/chrome/test/base/chromeos/ash_browser_test_starter.cc
+++ b/chrome/test/base/chromeos/ash_browser_test_starter.cc
@@ -26,7 +26,7 @@
 AshBrowserTestStarter::AshBrowserTestStarter() = default;
 AshBrowserTestStarter::~AshBrowserTestStarter() = default;
 
-bool AshBrowserTestStarter::HasLacrosArgument() {
+bool AshBrowserTestStarter::HasLacrosArgument() const {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       ash::switches::kLacrosChromePath);
 }
diff --git a/chrome/test/base/chromeos/ash_browser_test_starter.h b/chrome/test/base/chromeos/ash_browser_test_starter.h
index f4ca460..a5e96d19 100644
--- a/chrome/test/base/chromeos/ash_browser_test_starter.h
+++ b/chrome/test/base/chromeos/ash_browser_test_starter.h
@@ -22,7 +22,7 @@
   // Returns whether the --lacros-chrome-path is provided.
   // If returns false, we should not do any Lacros related testing
   // because the Lacros instance is not provided.
-  bool HasLacrosArgument();
+  bool HasLacrosArgument() const;
 
   // Prepares ash so it can work with Lacros. You should call this
   // in SetUpInProcessBrowserTestFixture().
diff --git a/chrome/test/data/extensions/api_test/wm_desks_private/background.js b/chrome/test/data/extensions/api_test/wm_desks_private/background.js
index 564c0dc2..8c11093 100644
--- a/chrome/test/data/extensions/api_test/wm_desks_private/background.js
+++ b/chrome/test/data/extensions/api_test/wm_desks_private/background.js
@@ -1,6 +1,7 @@
 // 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.
+var templateUuid;
 
 // Basic browser tests for the wmDesksPrivate API.
 chrome.test.runTests([
@@ -13,7 +14,36 @@
         chrome.test.callbackPass(function(deskTemplate) {
           chrome.test.assertEq(typeof deskTemplate, 'object');
           chrome.test.assertTrue(deskTemplate.hasOwnProperty('templateUuid'));
+          templateUuid = deskTemplate.templateUuid;
           chrome.test.assertTrue(deskTemplate.hasOwnProperty('templateName'));
         }));
   },
+
+  // Test launch empty desk with a desk name.
+  function testLaunchEmptyDeskWithName() {
+    // Launch empty desk with `deskName`
+    chrome.wmDesksPrivate.launchDesk({ "deskName": "test" },
+      chrome.test.callbackPass(function (result) {
+        // Desk uuid should be returned.
+        chrome.test.assertEq(typeof result, 'string');
+      }));
+  },
+
+  // Test launch a desk template to a new desk.
+  function testLaunchDeskTemplate() {
+    // Launch template to a new desk
+    chrome.wmDesksPrivate.launchDesk({ "templateUuid": templateUuid },
+      chrome.test.callbackPass(function (result) {
+        // Desk uuid should be returned.
+        chrome.test.assertEq(typeof result, 'string');
+      }));
+  },
+
+  // Test launch
+  function testLaunchDeskTemplateWithInvalidID() {
+    // Launch invalid template Uuid
+    chrome.wmDesksPrivate.launchDesk({ "templateUuid": "abcd" },
+      // Launch desk fail with invalid templateUuid
+      chrome.test.callbackFail("Storage error."));
+  }
 ]);
diff --git a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
index 6aa419f1..ff7a332e 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/ambient_subpage_element_test.ts
@@ -32,7 +32,10 @@
   const routerMock = TestBrowserProxy.fromClass(PersonalizationRouter);
 
   setup(() => {
-    loadTimeData.overrideValues({isAmbientModeAllowed: true});
+    loadTimeData.overrideValues({
+      isAmbientModeAllowed: true,
+      isAmbientModeAnimationEnabled: true,
+    });
     const mocks = baseSetup();
     ambientProvider = mocks.ambientProvider;
     personalizationStore = mocks.personalizationStore;
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts
index 61ef921..524ff15 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_theme_element_test.ts
@@ -44,7 +44,7 @@
 
     assertEquals(
         personalizationThemeElement.i18n('themeLabel'),
-        personalizationThemeElement.shadowRoot!.querySelector('p')!.innerText);
+        personalizationThemeElement.shadowRoot!.querySelector('h2')!.innerText);
   });
 
   test('sets color mode in store on first load', async () => {
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts
index c4f9f4f..6fac054 100644
--- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts
+++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_preview_element_test.ts
@@ -7,10 +7,8 @@
 import 'chrome://personalization/strings.m.js';
 import 'chrome://webui-test/mojo_webui_test_support.js';
 
-import {WallpaperPreview} from 'chrome://personalization/trusted/personalization_app.js';
-
+import {WallpaperPreview, WallpaperType} from 'chrome://personalization/trusted/personalization_app.js';
 import {assertEquals, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js';
-
 import {flushTasks, waitAfterNextRender} from 'chrome://webui-test/test_util.js';
 
 import {baseSetup, initElement} from './personalization_app_test_utils.js';
@@ -118,4 +116,29 @@
     assertEquals(
         null, wallpaperPreviewElement.shadowRoot!.querySelector('img'));
   });
+
+  test('shows managed icon when wallpaper is kPolicy', async () => {
+    // Start with non-managed wallpaper.
+    personalizationStore.data.wallpaper.currentSelected =
+        wallpaperProvider.currentWallpaper;
+
+    wallpaperPreviewElement = initElement(WallpaperPreview);
+    await waitAfterNextRender(wallpaperPreviewElement);
+
+    function getManagedIcon(): HTMLElement|null {
+      return wallpaperPreviewElement!.shadowRoot!.querySelector(
+          `iron-icon[icon='personalization:managed']`);
+    }
+
+    assertEquals(null, getManagedIcon(), 'no managed icon visible');
+
+    personalizationStore.data.wallpaper.currentSelected = {
+      ...personalizationStore.data.wallpaper.currentSelected,
+      type: WallpaperType.kPolicy
+    };
+    personalizationStore.notifyObservers();
+    await waitAfterNextRender(wallpaperPreviewElement);
+
+    assertTrue(!!getManagedIcon(), 'managed icon is shown');
+  });
 });
diff --git a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
index 0e810f6..601d346 100644
--- a/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/loading_page_test.js
@@ -7,32 +7,54 @@
 import {AppState} from 'chrome://scanning/scanning_app_types.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+import {MockController} from '../../mock_controller.js';
 import {flushTasks, isVisible} from '../../test_util.js';
 
+import {FakeMediaQueryList} from './scanning_app_test_utils.js';
+
 export function loadingPageTest() {
   const scanningSrcBase = 'chrome://scanning/';
 
   /** @type {?LoadingPageElement} */
   let loadingPage = null;
 
+  /** @type {{createFunctionMock: Function, reset: Function}} */
+  let mockController;
+
+  /** @type {?FakeMediaQueryList} */
+  let fakePrefersColorSchemeDarkMediaQuery = null;
+
   /**
-   * @suppress {visibility}
    * @param {boolean} enabled
+   * @return {!Promise}
    */
-  function setIsDarkModeEnabled_(enabled) {
+  function setFakePrefersColorSchemeDark(enabled) {
     assertTrue(!!loadingPage);
-    loadingPage.isDarkModeEnabled_ = enabled;
+    fakePrefersColorSchemeDarkMediaQuery.matches = enabled;
+
+    return flushTasks();
   }
 
+
   setup(() => {
     loadingPage = /** @type {!LoadingPageElement} */ (
         document.createElement('loading-page'));
     assertTrue(!!loadingPage);
     loadingPage.appState = AppState.GETTING_SCANNERS;
+
+    // Setup mock for matchMedia.
+    mockController = new MockController();
+    const mockMatchMedia =
+        mockController.createFunctionMock(window, 'matchMedia');
+    fakePrefersColorSchemeDarkMediaQuery =
+        new FakeMediaQueryList('(prefers-color-scheme: dark)');
+    mockMatchMedia.returnValue = fakePrefersColorSchemeDarkMediaQuery;
+
     document.body.appendChild(loadingPage);
   });
 
   teardown(() => {
+    mockController.reset();
     loadingPage.remove();
     loadingPage = null;
   });
@@ -88,14 +110,12 @@
         loadingPage.$$('#noScannersDiv img')));
 
     // Setup UI to display no scanners div.
-    setIsDarkModeEnabled_(false);
     loadingPage.appState = AppState.NO_SCANNERS;
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(false);
     assertEquals(getNoScannersSvg().src, lightModeSvg);
 
     // Mock media query state for dark mode.
-    setIsDarkModeEnabled_(true);
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(true);
     assertEquals(getNoScannersSvg().src, darkModeSvg);
   });
 
@@ -107,14 +127,12 @@
         (/** @type {!HTMLImageElement} */ (loadingPage.$$('#loadingDiv img')));
 
     // Setup UI to display no scanners div.
-    setIsDarkModeEnabled_(false);
     loadingPage.appState = AppState.NO_SCANNERS;
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(false);
     assertEquals(getLoadingSvg().src, lightModeSvg);
 
     // Mock media query state for dark mode.
-    setIsDarkModeEnabled_(true);
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(true);
     assertEquals(getLoadingSvg().src, darkModeSvg);
   });
 }
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
index 5e98dc6..4dd716f 100644
--- a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
+++ b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
@@ -11,8 +11,10 @@
 import {ScanningBrowserProxyImpl} from 'chrome://scanning/scanning_browser_proxy.js';
 
 import {assertEquals, assertFalse, assertNotEquals, assertTrue} from '../../chai_assert.js';
+import {MockController} from '../../mock_controller.js';
 import {flushTasks, isVisible, waitAfterNextRender} from '../../test_util.js';
 
+import {FakeMediaQueryList} from './scanning_app_test_utils.js';
 import {TestScanningBrowserProxy} from './test_scanning_browser_proxy.js';
 
 /** @implements {ash.common.mojom.AccessibilityFeaturesInterface} */
@@ -62,13 +64,21 @@
   /** @type {!HTMLElement} */
   let cancelingProgress;
 
+  /** @type {{createFunctionMock: Function, reset: Function}} */
+  let mockController;
+
+  /** @type {?FakeMediaQueryList} */
+  let fakePrefersColorSchemeDarkMediaQuery;
+
   /**
-   * @suppress {visibility}
    * @param {boolean} enabled
+   * @return {!Promise}
    */
-  function setIsDarkModeEnabled_(enabled) {
+  function setFakePrefersColorSchemeDark(enabled) {
     assertTrue(!!scanPreview);
-    scanPreview.isDarkModeEnabled_ = enabled;
+    fakePrefersColorSchemeDarkMediaQuery.matches = enabled;
+
+    return flushTasks();
   }
 
   setup(() => {
@@ -78,6 +88,15 @@
         document.createElement('scan-preview'));
     assertTrue(!!scanPreview);
     ScanningBrowserProxyImpl.instance_ = new TestScanningBrowserProxy();
+
+    // Setup mock for matchMedia.
+    mockController = new MockController();
+    const mockMatchMedia =
+        mockController.createFunctionMock(window, 'matchMedia');
+    fakePrefersColorSchemeDarkMediaQuery =
+        new FakeMediaQueryList('(prefers-color-scheme: dark)');
+    mockMatchMedia.returnValue = fakePrefersColorSchemeDarkMediaQuery;
+
     document.body.appendChild(scanPreview);
 
     helpOrProgress =
@@ -96,6 +115,7 @@
     if (scanPreview) {
       scanPreview.remove();
     }
+    mockController.reset();
     scanPreview = null;
   });
 
@@ -431,13 +451,11 @@
         (/** @type {!HTMLImageElement} */ (scanPreview.$$('#readyToScanImg')));
 
     // Mock media query state for light mode.
-    setIsDarkModeEnabled_(false);
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(false);
     assertEquals(getReadyToScanSvg().src, lightModeSvg);
 
     // Mock media query state for dark mode.
-    setIsDarkModeEnabled_(true);
-    await flushTasks();
+    await setFakePrefersColorSchemeDark(true);
     assertEquals(getReadyToScanSvg().src, darkModeSvg);
   });
 }
diff --git a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
index 447f8e31e..a75fd35 100644
--- a/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
+++ b/chrome/test/data/webui/chromeos/scanning/scanning_app_test_utils.js
@@ -2,7 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 import {alphabeticalCompare} from 'chrome://scanning/scanning_app_util.js';
-import {assertTrue} from '../../chai_assert.js';
+
+import {assertEquals, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.js';
 
 /**
@@ -76,3 +77,64 @@
   select.dispatchEvent(new CustomEvent('change'));
   return flushTasks();
 }
+
+/** @typedef {function(string, {media: string, matches: boolean})} */
+let MediaQueryListEventListener;
+
+/**
+ * Fake MediaQueryList for mocking behavior of |window.matchMedia|.
+ * @extends {EventTarget}
+ * @implements {MediaQueryList}
+ * @suppress {checkTypes} Type checker incorrectly states class cannot be
+ * extended.
+ */
+export class FakeMediaQueryList extends EventTarget {
+  constructor(media) {
+    super();
+    /** @type {string} */
+    this.media_ = media;
+    /** @type {boolean} */
+    this.matches_ = false;
+    /** @type {?MediaQueryListEventListener} */
+    this.listener_ = null;
+  }
+
+  /** @param {!Function} listener */
+  addListener(listener) {
+    this.listener_ = listener;
+  }
+
+  /** @param {!Function} listener */
+  removeListener(listener) {
+    this.listener_ = null;
+  }
+
+  onchange() {
+    if (!this.listener_) {
+      return;
+    }
+
+    this.listener_(new window.MediaQueryListEvent(
+        'change', {media: this.media_, matches: this.matches_}));
+  }
+
+  /** @return {string} */
+  get media() {
+    return this.media_;
+  }
+
+  /** @return {boolean} */
+  get matches() {
+    return this.matches_;
+  }
+
+  /** @param {boolean} matches */
+  set matches(matches) {
+    if (this.matches_ === matches) {
+      return;
+    }
+
+    this.matches_ = matches;
+    this.onchange();
+  }
+}
diff --git a/chrome/updater/app/app_server_unittest.cc b/chrome/updater/app/app_server_unittest.cc
index cae1065..05c8b47 100644
--- a/chrome/updater/app/app_server_unittest.cc
+++ b/chrome/updater/app/app_server_unittest.cc
@@ -65,8 +65,8 @@
 void ClearPrefs() {
   const UpdaterScope updater_scope = GetUpdaterScope();
   for (const absl::optional<base::FilePath>& path :
-       {GetBaseDataDirectory(updater_scope),
-        GetVersionedDataDirectory(updater_scope)}) {
+       {GetBaseDirectory(updater_scope),
+        GetVersionedDirectory(updater_scope)}) {
     ASSERT_TRUE(path);
     ASSERT_TRUE(
         base::DeleteFile(path->Append(FILE_PATH_LITERAL("prefs.json"))));
diff --git a/chrome/updater/app/app_uninstall.cc b/chrome/updater/app/app_uninstall.cc
index accf14f..1341c0c 100644
--- a/chrome/updater/app/app_uninstall.cc
+++ b/chrome/updater/app/app_uninstall.cc
@@ -43,7 +43,7 @@
 // given `scope`.
 void UninstallOtherVersions(UpdaterScope scope) {
   const absl::optional<base::FilePath> updater_folder_path =
-      GetBaseInstallDirectory(scope);
+      GetUpdaterFolderPath(scope);
   if (!updater_folder_path) {
     LOG(ERROR) << "Failed to get updater folder path.";
     return;
@@ -52,7 +52,7 @@
                                        base::FileEnumerator::DIRECTORIES);
   for (base::FilePath version_folder_path = file_enumerator.Next();
        !version_folder_path.empty() &&
-       version_folder_path != GetVersionedInstallDirectory(scope);
+       version_folder_path != GetVersionedUpdaterFolderPath(scope);
        version_folder_path = file_enumerator.Next()) {
     const base::FilePath version_executable_path =
         version_folder_path.Append(GetExecutableRelativePath());
diff --git a/chrome/updater/app/server/win/server.cc b/chrome/updater/app/server/win/server.cc
index b8751866..eef6290 100644
--- a/chrome/updater/app/server/win/server.cc
+++ b/chrome/updater/app/server/win/server.cc
@@ -293,7 +293,7 @@
   std::unique_ptr<WorkItemList> list(WorkItem::CreateWorkItemList());
 
   const absl::optional<base::FilePath> versioned_directory =
-      GetVersionedDataDirectory(updater_scope());
+      GetVersionedDirectory(updater_scope());
   if (!versioned_directory)
     return false;
 
diff --git a/chrome/updater/constants.h b/chrome/updater/constants.h
index f7da595..26b7f02 100644
--- a/chrome/updater/constants.h
+++ b/chrome/updater/constants.h
@@ -265,7 +265,7 @@
 constexpr int kErrorFailedToDeleteDataFolder = 17;
 
 // Failed to get versioned updater folder path.
-constexpr int kErrorFailedToGetVersionedInstallDirectory = 18;
+constexpr int kErrorFailedToGetVersionedUpdaterFolderPath = 18;
 
 // Failed to get the installed app bundle path.
 constexpr int kErrorFailedToGetAppBundlePath = 19;
diff --git a/chrome/updater/crash_client.cc b/chrome/updater/crash_client.cc
index 055b8c7f..9ab37b9 100644
--- a/chrome/updater/crash_client.cc
+++ b/chrome/updater/crash_client.cc
@@ -56,7 +56,7 @@
   base::PathService::Get(base::FILE_EXE, &handler_path);
 
   const absl::optional<base::FilePath> database_path =
-      GetVersionedDataDirectory(updater_scope);
+      GetVersionedDirectory(updater_scope);
   if (!database_path) {
     LOG(ERROR) << "Failed to get the database path.";
     return false;
diff --git a/chrome/updater/crash_reporter.cc b/chrome/updater/crash_reporter.cc
index 89d3c4b..66077bb 100644
--- a/chrome/updater/crash_reporter.cc
+++ b/chrome/updater/crash_reporter.cc
@@ -73,7 +73,7 @@
   base::PathService::Get(base::FILE_EXE, &handler_path);
 
   const absl::optional<base::FilePath> database_path =
-      GetVersionedDataDirectory(updater_scope);
+      GetVersionedDirectory(updater_scope);
   if (!database_path) {
     LOG(ERROR) << "Failed to get the database path.";
     return;
diff --git a/chrome/updater/device_management/dm_storage.cc b/chrome/updater/device_management/dm_storage.cc
index 1c22bed..a9df20a 100644
--- a/chrome/updater/device_management/dm_storage.cc
+++ b/chrome/updater/device_management/dm_storage.cc
@@ -205,7 +205,7 @@
 
 scoped_refptr<DMStorage> GetDefaultDMStorage() {
   const absl::optional<base::FilePath> updater_versioned_path =
-      GetVersionedDataDirectory(GetUpdaterScope());
+      GetVersionedDirectory(GetUpdaterScope());
   if (!updater_versioned_path)
     return nullptr;
 
diff --git a/chrome/updater/external_constants_builder.cc b/chrome/updater/external_constants_builder.cc
index c2ed04c1..70aa4e1 100644
--- a/chrome/updater/external_constants_builder.cc
+++ b/chrome/updater/external_constants_builder.cc
@@ -119,7 +119,7 @@
 
 bool ExternalConstantsBuilder::Overwrite() {
   const absl::optional<base::FilePath> base_path =
-      GetBaseDataDirectory(GetUpdaterScope());
+      GetBaseDirectory(GetUpdaterScope());
   if (!base_path) {
     LOG(ERROR) << "Can't find base directory; can't save constant overrides.";
     return false;
diff --git a/chrome/updater/external_constants_builder_unittest.cc b/chrome/updater/external_constants_builder_unittest.cc
index 5535672b..4b3b354 100644
--- a/chrome/updater/external_constants_builder_unittest.cc
+++ b/chrome/updater/external_constants_builder_unittest.cc
@@ -28,7 +28,7 @@
 
 void DeleteOverridesFile() {
   const absl::optional<base::FilePath> target =
-      GetBaseDataDirectory(GetUpdaterScope());
+      GetBaseDirectory(GetUpdaterScope());
   if (!target) {
     LOG(ERROR) << "Could not get base directory to clean out overrides file.";
     return;
diff --git a/chrome/updater/external_constants_override.cc b/chrome/updater/external_constants_override.cc
index db025e4..5186281 100644
--- a/chrome/updater/external_constants_override.cc
+++ b/chrome/updater/external_constants_override.cc
@@ -152,7 +152,7 @@
 ExternalConstantsOverrider::FromDefaultJSONFile(
     scoped_refptr<ExternalConstants> next_provider) {
   const absl::optional<base::FilePath> data_dir_path =
-      GetBaseDataDirectory(GetUpdaterScope());
+      GetBaseDirectory(GetUpdaterScope());
   if (!data_dir_path) {
     LOG(ERROR) << "Cannot find app data path.";
     return nullptr;
diff --git a/chrome/updater/installer.cc b/chrome/updater/installer.cc
index d0a4415..03dc024 100644
--- a/chrome/updater/installer.cc
+++ b/chrome/updater/installer.cc
@@ -41,7 +41,7 @@
 // identified by the |app_id|.
 absl::optional<base::FilePath> GetAppInstallDir(UpdaterScope scope,
                                                 const std::string& app_id) {
-  absl::optional<base::FilePath> app_install_dir = GetBaseDataDirectory(scope);
+  absl::optional<base::FilePath> app_install_dir = GetBaseDirectory(scope);
   if (!app_install_dir)
     return absl::nullopt;
 
diff --git a/chrome/updater/mac/setup/keystone.mm b/chrome/updater/mac/setup/keystone.mm
index 8fce8b3..e5ba527 100644
--- a/chrome/updater/mac/setup/keystone.mm
+++ b/chrome/updater/mac/setup/keystone.mm
@@ -70,9 +70,9 @@
     if (!base::SetPosixFilePermissions(
             GetLibraryFolderPath(scope)->Append(COMPANY_SHORTNAME_STRING),
             kPermissionsMask) ||
-        !base::SetPosixFilePermissions(*GetBaseInstallDirectory(scope),
+        !base::SetPosixFilePermissions(*GetUpdaterFolderPath(scope),
                                        kPermissionsMask) ||
-        !base::SetPosixFilePermissions(*GetVersionedInstallDirectory(scope),
+        !base::SetPosixFilePermissions(*GetVersionedUpdaterFolderPath(scope),
                                        kPermissionsMask) ||
         !base::SetPosixFilePermissions(dest_path, kPermissionsMask)) {
       LOG(ERROR) << "Failed to set permissions to drwxr-xr-x at "
diff --git a/chrome/updater/mac/setup/setup.mm b/chrome/updater/mac/setup/setup.mm
index a0166ab..a307780 100644
--- a/chrome/updater/mac/setup/setup.mm
+++ b/chrome/updater/mac/setup/setup.mm
@@ -101,9 +101,9 @@
     if (!base::SetPosixFilePermissions(
             GetLibraryFolderPath(scope)->Append(COMPANY_SHORTNAME_STRING),
             kPermissionsMask) ||
-        !base::SetPosixFilePermissions(*GetBaseInstallDirectory(scope),
+        !base::SetPosixFilePermissions(*GetUpdaterFolderPath(scope),
                                        kPermissionsMask) ||
-        !base::SetPosixFilePermissions(*GetVersionedInstallDirectory(scope),
+        !base::SetPosixFilePermissions(*GetVersionedUpdaterFolderPath(scope),
                                        kPermissionsMask)) {
       LOG(ERROR) << "Failed to set permissions to drwxr-xr-x at "
                  << dest_path.value().c_str();
@@ -317,15 +317,15 @@
 }
 
 bool DeleteInstallFolder(UpdaterScope scope) {
-  return DeleteFolder(GetBaseInstallDirectory(scope));
+  return DeleteFolder(GetUpdaterFolderPath(scope));
 }
 
 bool DeleteCandidateInstallFolder(UpdaterScope scope) {
-  return DeleteFolder(GetVersionedInstallDirectory(scope));
+  return DeleteFolder(GetVersionedUpdaterFolderPath(scope));
 }
 
 bool DeleteDataFolder(UpdaterScope scope) {
-  return DeleteFolder(GetBaseDataDirectory(scope));
+  return DeleteFolder(GetBaseDirectory(scope));
 }
 
 void CleanAfterInstallFailure(UpdaterScope scope) {
@@ -359,10 +359,10 @@
 
 int DoSetup(UpdaterScope scope) {
   const absl::optional<base::FilePath> dest_path =
-      GetVersionedInstallDirectory(scope);
+      GetVersionedUpdaterFolderPath(scope);
 
   if (!dest_path)
-    return kErrorFailedToGetVersionedInstallDirectory;
+    return kErrorFailedToGetVersionedUpdaterFolderPath;
   if (!CopyBundle(*dest_path, scope))
     return kErrorFailedToCopyBundle;
 
@@ -408,9 +408,9 @@
 
 int PromoteCandidate(UpdaterScope scope) {
   const absl::optional<base::FilePath> dest_path =
-      GetVersionedInstallDirectory(scope);
+      GetVersionedUpdaterFolderPath(scope);
   if (!dest_path)
-    return kErrorFailedToGetVersionedInstallDirectory;
+    return kErrorFailedToGetVersionedUpdaterFolderPath;
   const base::FilePath updater_executable_path =
       dest_path->Append(GetExecutableRelativePath());
 
@@ -428,36 +428,34 @@
 
 #pragma mark Uninstall
 int UninstallCandidate(UpdaterScope scope) {
-  int error = kErrorOk;
-
-  if (!DeleteCandidateInstallFolder(scope) ||
-      !DeleteFolder(GetVersionedDataDirectory(scope))) {
-    error = kErrorFailedToDeleteFolder;
-  }
+  if (!DeleteCandidateInstallFolder(scope))
+    return kErrorFailedToDeleteFolder;
 
   if (!RemoveUpdateWakeJobFromLaunchd(scope))
-    error = kErrorFailedToRemoveWakeJobFromLaunchd;
+    return kErrorFailedToRemoveWakeJobFromLaunchd;
 
   // Removing the Update Internal job has to be the last step because launchd is
   // likely to terminate the current process. Clients should expect the
   // connection to invalidate (possibly with an interruption beforehand) as a
   // result of service uninstallation.
   if (!RemoveUpdateServiceInternalJobFromLaunchd(scope))
-    error = kErrorFailedToRemoveUpdateServiceInternalJobFromLaunchd;
+    return kErrorFailedToRemoveUpdateServiceInternalJobFromLaunchd;
 
-  return error;
+  return kErrorOk;
 }
 
 int Uninstall(UpdaterScope scope) {
   VLOG(1) << base::CommandLine::ForCurrentProcess()->GetCommandLineString()
           << " : " << __func__;
-  int exit = UninstallCandidate(scope);
+  const int exit = UninstallCandidate(scope);
+  if (exit != kErrorOk)
+    return exit;
 
   if (!RemoveUpdateServiceJobFromLaunchd(scope))
-    exit = kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd;
+    return kErrorFailedToRemoveActiveUpdateServiceJobFromLaunchd;
 
   if (!DeleteInstallFolder(scope))
-    exit = kErrorFailedToDeleteFolder;
+    return kErrorFailedToDeleteFolder;
 
   base::ThreadPool::PostTask(FROM_HERE,
                              {base::MayBlock(), base::WithBaseSyncPrimitives()},
@@ -468,7 +466,7 @@
   // it is not always possible to delete the data folder.
   DeleteDataFolder(scope);
 
-  return exit;
+  return kErrorOk;
 }
 
 }  // namespace updater
diff --git a/chrome/updater/prefs.cc b/chrome/updater/prefs.cc
index 97dca73..6e9c350 100644
--- a/chrome/updater/prefs.cc
+++ b/chrome/updater/prefs.cc
@@ -94,7 +94,7 @@
     return nullptr;
 
   const absl::optional<base::FilePath> global_prefs_dir =
-      GetBaseDataDirectory(scope);
+      GetBaseDirectory(scope);
   if (!global_prefs_dir)
     return nullptr;
   VLOG(1) << "global_prefs_dir: " << global_prefs_dir;
@@ -117,7 +117,7 @@
 
 scoped_refptr<LocalPrefs> CreateLocalPrefs(UpdaterScope scope) {
   const absl::optional<base::FilePath> local_prefs_dir =
-      GetVersionedDataDirectory(scope);
+      GetVersionedDirectory(scope);
   if (!local_prefs_dir)
     return nullptr;
 
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc
index 959a1d9..987ca959 100644
--- a/chrome/updater/test/integration_tests_impl.cc
+++ b/chrome/updater/test/integration_tests_impl.cc
@@ -291,7 +291,7 @@
 
   // Invoke the wake client of that version.
   base::CommandLine command_line(
-      GetVersionedInstallDirectory(scope, active_version)
+      GetVersionedUpdaterFolderPathForVersion(scope, active_version)
           ->Append(GetExecutableRelativePath()));
   command_line.AppendSwitch(kWakeSwitch);
   int exit_code = -1;
diff --git a/chrome/updater/test/integration_tests_mac.mm b/chrome/updater/test/integration_tests_mac.mm
index 39399253..d1d1d780 100644
--- a/chrome/updater/test/integration_tests_mac.mm
+++ b/chrome/updater/test/integration_tests_mac.mm
@@ -266,7 +266,7 @@
   Launchd::Type launchd_type = LaunchdType(scope);
 
   absl::optional<base::FilePath> versioned_folder_path =
-      GetVersionedInstallDirectory(scope);
+      GetVersionedUpdaterFolderPath(scope);
   EXPECT_TRUE(versioned_folder_path);
   if (versioned_folder_path)
     EXPECT_FALSE(base::PathExists(*versioned_folder_path));
diff --git a/chrome/updater/util.cc b/chrome/updater/util.cc
index 7422271..7aa105d 100644
--- a/chrome/updater/util.cc
+++ b/chrome/updater/util.cc
@@ -101,7 +101,7 @@
 
 }  // namespace
 
-absl::optional<base::FilePath> GetBaseDataDirectory(UpdaterScope scope) {
+absl::optional<base::FilePath> GetBaseDirectory(UpdaterScope scope) {
   absl::optional<base::FilePath> app_data_dir;
 #if BUILDFLAG(IS_WIN)
   base::FilePath path;
@@ -130,9 +130,8 @@
   return product_data_dir;
 }
 
-absl::optional<base::FilePath> GetVersionedDataDirectory(UpdaterScope scope) {
-  const absl::optional<base::FilePath> product_dir =
-      GetBaseDataDirectory(scope);
+absl::optional<base::FilePath> GetVersionedDirectory(UpdaterScope scope) {
+  const absl::optional<base::FilePath> product_dir = GetBaseDirectory(scope);
   if (!product_dir) {
     LOG(ERROR) << "Failed to get the base directory.";
     return absl::nullopt;
@@ -147,18 +146,19 @@
   return versioned_dir;
 }
 
-absl::optional<base::FilePath> GetVersionedInstallDirectory(
+absl::optional<base::FilePath> GetVersionedUpdaterFolderPathForVersion(
     UpdaterScope scope,
     const base::Version& version) {
-  const absl::optional<base::FilePath> path = GetBaseInstallDirectory(scope);
+  const absl::optional<base::FilePath> path = GetUpdaterFolderPath(scope);
   if (!path)
     return absl::nullopt;
   return path->AppendASCII(version.GetString());
 }
 
-absl::optional<base::FilePath> GetVersionedInstallDirectory(
+absl::optional<base::FilePath> GetVersionedUpdaterFolderPath(
     UpdaterScope scope) {
-  return GetVersionedInstallDirectory(scope, base::Version(kUpdaterVersion));
+  return GetVersionedUpdaterFolderPathForVersion(
+      scope, base::Version(kUpdaterVersion));
 }
 
 TagParsingResult::TagParsingResult() = default;
@@ -225,7 +225,7 @@
 void InitLogging(UpdaterScope updater_scope) {
   logging::LoggingSettings settings;
   const absl::optional<base::FilePath> log_dir =
-      GetBaseDataDirectory(updater_scope);
+      GetBaseDirectory(updater_scope);
   if (!log_dir) {
     LOG(ERROR) << "Error getting base dir.";
     return;
@@ -264,7 +264,7 @@
 #if BUILDFLAG(IS_LINUX)
 
 // TODO(crbug.com/1276188) - implement the functions below.
-absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) {
+absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) {
   NOTIMPLEMENTED();
   return absl::nullopt;
 }
diff --git a/chrome/updater/util.h b/chrome/updater/util.h
index dc0a2a7..90016bbb 100644
--- a/chrome/updater/util.h
+++ b/chrome/updater/util.h
@@ -43,32 +43,34 @@
 
 enum class UpdaterScope;
 
-// Returns the base data directory common to all versions of the updater. For
+// Returns the base directory common to all versions of the updater. For
 // instance, this function may return %localappdata%\Chromium\ChromiumUpdater
-// for a user install. Creates the directory if it does not exist.
-absl::optional<base::FilePath> GetBaseDataDirectory(UpdaterScope scope);
+// for a user install.
+absl::optional<base::FilePath> GetBaseDirectory(UpdaterScope scope);
 
-// Returns the versioned data directory under which the running version of the
-// updater stores its data. For instance, this function may return
-// %localappdata%\Chromium\ChromiumUpdater\1.2.3.4 for a user install. Creates
-// the directory if it does not exit.
-absl::optional<base::FilePath> GetVersionedDataDirectory(UpdaterScope scope);
+// Returns a versioned directory under which the running version of the updater
+// stores its files and data. For instance, this function may return
+// %localappdata%\Chromium\ChromiumUpdater\1.2.3.4 for a user install.
+absl::optional<base::FilePath> GetVersionedDirectory(UpdaterScope scope);
 
-// Returns the versioned install directory under which the program stores its
-// executables. For example, on macOS this function may return
-// ~/Library/Google/GoogleUpdater/88.0.4293.0 (/Library for system). Does not
-// create the directory if it does not exist.
-absl::optional<base::FilePath> GetVersionedInstallDirectory(
+// For user installations:
+// ~/Library/Google/GoogleUpdater/88.0.4293.0
+// For system installations:
+// /Library/Google/GoogleUpdater/88.0.4293.0
+absl::optional<base::FilePath> GetVersionedUpdaterFolderPathForVersion(
     UpdaterScope scope,
     const base::Version& version);
 
-// Simpler form of GetVersionedInstallDirectory for the currently running
-// version of the updater.
-absl::optional<base::FilePath> GetVersionedInstallDirectory(UpdaterScope scope);
+// The same as GetVersionedUpdaterFolderPathForVersion, where the version is
+// kUpdaterVersion.
+absl::optional<base::FilePath> GetVersionedUpdaterFolderPath(
+    UpdaterScope scope);
 
-// Returns the base install directory common to all versions of the updater.
-// Does not create the directory if it does not exist.
-absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope);
+// For user installations:
+// ~/Library/Google/GoogleUpdater
+// For system installations:
+// /Library/Google/GoogleUpdater
+absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope);
 
 #if BUILDFLAG(IS_MAC)
 // For example: ~/Library/Google/GoogleUpdater/88.0.4293.0/GoogleUpdater.app
diff --git a/chrome/updater/util_mac.mm b/chrome/updater/util_mac.mm
index ca0fba64..d755f00 100644
--- a/chrome/updater/util_mac.mm
+++ b/chrome/updater/util_mac.mm
@@ -63,7 +63,7 @@
   return exit_code <= 1;
 }
 
-absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) {
+absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) {
   absl::optional<base::FilePath> path = GetLibraryFolderPath(scope);
   if (!path)
     return absl::nullopt;
@@ -74,14 +74,14 @@
     UpdaterScope scope,
     const base::Version& version) {
   absl::optional<base::FilePath> path =
-      GetVersionedInstallDirectory(scope, version);
+      GetVersionedUpdaterFolderPathForVersion(scope, version);
   if (!path)
     return absl::nullopt;
   return path->Append(ExecutableFolderPath());
 }
 
 absl::optional<base::FilePath> GetUpdaterAppBundlePath(UpdaterScope scope) {
-  absl::optional<base::FilePath> path = GetVersionedInstallDirectory(scope);
+  absl::optional<base::FilePath> path = GetVersionedUpdaterFolderPath(scope);
   if (!path)
     return absl::nullopt;
   return path->Append(
@@ -89,7 +89,7 @@
 }
 
 absl::optional<base::FilePath> GetUpdaterExecutablePath(UpdaterScope scope) {
-  absl::optional<base::FilePath> path = GetVersionedInstallDirectory(scope);
+  absl::optional<base::FilePath> path = GetVersionedUpdaterFolderPath(scope);
   if (!path)
     return absl::nullopt;
   return path->Append(ExecutableFolderPath())
diff --git a/chrome/updater/util_win.cc b/chrome/updater/util_win.cc
index 99a524d..f04f08ff 100644
--- a/chrome/updater/util_win.cc
+++ b/chrome/updater/util_win.cc
@@ -46,7 +46,7 @@
   return std::string();
 }
 
-absl::optional<base::FilePath> GetBaseInstallDirectory(UpdaterScope scope) {
+absl::optional<base::FilePath> GetUpdaterFolderPath(UpdaterScope scope) {
   base::FilePath app_data_dir;
   if (!base::PathService::Get(scope == UpdaterScope::kSystem
                                   ? base::DIR_PROGRAM_FILES
diff --git a/chrome/updater/win/setup/setup.cc b/chrome/updater/win/setup/setup.cc
index 345c798..ca57f339 100644
--- a/chrome/updater/win/setup/setup.cc
+++ b/chrome/updater/win/setup/setup.cc
@@ -118,9 +118,9 @@
     return -1;
   }
   const absl::optional<base::FilePath> versioned_dir =
-      GetVersionedDataDirectory(scope);
+      GetVersionedDirectory(scope);
   if (!versioned_dir) {
-    LOG(ERROR) << "GetVersionedDataDirectory failed.";
+    LOG(ERROR) << "GetVersionedDirectory failed.";
     return -1;
   }
   base::FilePath exe_path;
diff --git a/chrome/updater/win/setup/uninstall.cc b/chrome/updater/win/setup/uninstall.cc
index acf1716..0407a60 100644
--- a/chrome/updater/win/setup/uninstall.cc
+++ b/chrome/updater/win/setup/uninstall.cc
@@ -94,14 +94,14 @@
 
 int RunUninstallScript(UpdaterScope scope, bool uninstall_all) {
   const absl::optional<base::FilePath> versioned_dir =
-      GetVersionedDataDirectory(scope);
+      GetVersionedDirectory(scope);
   if (!versioned_dir) {
-    LOG(ERROR) << "GetVersionedDataDirectory failed.";
+    LOG(ERROR) << "GetVersionedDirectory failed.";
     return kErrorNoVersionedDirectory;
   }
-  const absl::optional<base::FilePath> base_dir = GetBaseDataDirectory(scope);
+  const absl::optional<base::FilePath> base_dir = GetBaseDirectory(scope);
   if (scope == UpdaterScope::kSystem && !base_dir) {
-    LOG(ERROR) << "GetBaseDataDirectory failed.";
+    LOG(ERROR) << "GetBaseDirectory failed.";
     return kErrorNoBaseDirectory;
   }
 
diff --git a/chrome/updater/win/task_scheduler_unittest.cc b/chrome/updater/win/task_scheduler_unittest.cc
index 231de494..f1741b9 100644
--- a/chrome/updater/win/task_scheduler_unittest.cc
+++ b/chrome/updater/win/task_scheduler_unittest.cc
@@ -105,7 +105,7 @@
 
   void DeleteLogFile() {
     const absl::optional<base::FilePath> log_dir =
-        GetBaseDataDirectory(GetTestScope());
+        GetBaseDirectory(GetTestScope());
     if (log_dir) {
       base::DeleteFile(log_dir->Append(FILE_PATH_LITERAL("updater.log")));
     }
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 024eec11..ae0de0b 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-14844.0.0
\ No newline at end of file
+14906.0.0
\ No newline at end of file
diff --git a/chromeos/ash/components/cros_elements/BUILD.gn b/chromeos/ash/components/cros_elements/BUILD.gn
index 54fccc2..7be00d3 100644
--- a/chromeos/ash/components/cros_elements/BUILD.gn
+++ b/chromeos/ash/components/cros_elements/BUILD.gn
@@ -13,7 +13,7 @@
 
   input_files = [ "button/button.js" ]
 
-  deps = [ "button" ]
+  public_deps = [ "button" ]
 
   input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
   resource_path_prefix = "cros_elements"
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 6084cd3..bf2ef769 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -3127,7 +3127,7 @@
         Install is complete. Preparing to restart...
       </message>
       <message name="IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE" desc="The message when firmware installation is complete and the device has rebooted.">
-        Installation complete.
+        Install is complete. You can now remove your USB drive or SD card.
       </message>
       <!-- Onboarding update page -->
       <message name="IDS_SHIMLESS_RMA_ONBOARDING_UPDATE_PROGRESS" translateable="false" desc="The update progress label.">
diff --git a/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1
index f08963f..f58f76e 100644
--- a/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1
+++ b/chromeos/chromeos_strings_grd/IDS_SHIMLESS_RMA_FIRMWARE_UPDATE_COMPLETE.png.sha1
@@ -1 +1 @@
-752fac072ce209d2098651bc8f10558d36f9e3bc
\ No newline at end of file
+d252ae7b76c89138f4afa159557c2942b9b85d1a
\ No newline at end of file
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc
index 9a04086..0e8d0520 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -408,7 +408,8 @@
 }
 
 bool FakeSessionManagerClient::RequestBrowserDataMigration(
-    const cryptohome::AccountIdentifier& cryptohome_id) {
+    const cryptohome::AccountIdentifier& cryptohome_id,
+    const bool is_move) {
   request_browser_data_migration_called_ = true;
 
   return true;
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h
index 9f4a5e9d..112f53ea 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -104,7 +104,8 @@
   void NotifyLockScreenShown() override;
   void NotifyLockScreenDismissed() override;
   bool RequestBrowserDataMigration(
-      const cryptohome::AccountIdentifier& cryptohome_id) override;
+      const cryptohome::AccountIdentifier& cryptohome_id,
+      const bool is_move) override;
   void RetrieveActiveSessions(ActiveSessionsCallback callback) override;
   void RetrieveDevicePolicy(RetrievePolicyCallback callback) override;
   RetrievePolicyResponseType BlockingRetrieveDevicePolicy(
diff --git a/chromeos/dbus/session_manager/session_manager_client.cc b/chromeos/dbus/session_manager/session_manager_client.cc
index 22f1e236..c140b00 100644
--- a/chromeos/dbus/session_manager/session_manager_client.cc
+++ b/chromeos/dbus/session_manager/session_manager_client.cc
@@ -25,6 +25,7 @@
 #include "base/memory/writable_shared_memory_region.h"
 #include "base/path_service.h"
 #include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/unguessable_token.h"
 #include "chromeos/dbus/common/blocking_method_caller.h"
@@ -403,18 +404,24 @@
   }
 
   bool RequestBrowserDataMigration(
-      const cryptohome::AccountIdentifier& cryptohome_id) override {
+      const cryptohome::AccountIdentifier& cryptohome_id,
+      const bool is_move) override {
     dbus::MethodCall method_call(
         login_manager::kSessionManagerInterface,
         login_manager::kSessionManagerStartBrowserDataMigration);
     dbus::MessageWriter writer(&method_call);
     writer.AppendString(cryptohome_id.account_id());
+    writer.AppendBool(is_move);
     dbus::ScopedDBusError error;
     std::unique_ptr<dbus::Response> response =
         blocking_method_caller_->CallMethodAndBlockWithError(&method_call,
                                                              &error);
     if (!response) {
-      LOG(ERROR) << "RequestBrowserDataMigration failed.";
+      LOG(ERROR) << "RequestBrowserDataMigration failed"
+                 << (error.is_set()
+                         ? base::StringPrintf(" :%s:%s", error.name(),
+                                              error.message())
+                         : ".");
       return false;
     }
 
diff --git a/chromeos/dbus/session_manager/session_manager_client.h b/chromeos/dbus/session_manager/session_manager_client.h
index 3552da8..325f342 100644
--- a/chromeos/dbus/session_manager/session_manager_client.h
+++ b/chromeos/dbus/session_manager/session_manager_client.h
@@ -258,7 +258,8 @@
   // successful. The callback is passed true if the DBus call is successful and
   // false otherwise.
   virtual bool RequestBrowserDataMigration(
-      const cryptohome::AccountIdentifier& cryptohome_id) = 0;
+      const cryptohome::AccountIdentifier& cryptohome_id,
+      const bool is_move) = 0;
 
   // Map that is used to describe the set of active user sessions where |key|
   // is cryptohome id and |value| is user_id_hash.
diff --git a/chromeos/ui/base/window_properties.cc b/chromeos/ui/base/window_properties.cc
index ae4e673..aecb0790 100644
--- a/chromeos/ui/base/window_properties.cc
+++ b/chromeos/ui/base/window_properties.cc
@@ -55,6 +55,6 @@
                              kWindowStateTypeKey,
                              WindowStateType::kDefault)
 
-DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowFloatTypeKey, false)
+DEFINE_UI_CLASS_PROPERTY_KEY(bool, kWindowToggleFloatKey, false)
 
 }  // namespace chromeos
diff --git a/chromeos/ui/base/window_properties.h b/chromeos/ui/base/window_properties.h
index 5911b7b..31c7119 100644
--- a/chromeos/ui/base/window_properties.h
+++ b/chromeos/ui/base/window_properties.h
@@ -116,9 +116,9 @@
 COMPONENT_EXPORT(CHROMEOS_UI_BASE)
 extern const ui::ClassProperty<WindowStateType>* const kWindowStateTypeKey;
 
-// A property key to indicate Float window state.
+// A property key to toggle Float window state change.
 COMPONENT_EXPORT(CHROMEOS_UI_BASE)
-extern const ui::ClassProperty<bool>* const kWindowFloatTypeKey;
+extern const ui::ClassProperty<bool>* const kWindowToggleFloatKey;
 
 // A property key whose value is shown in alt-tab/overview mode. If non-value
 // is set, the window's title is used.
diff --git a/chromeos/ui/base/window_state_type.cc b/chromeos/ui/base/window_state_type.cc
index 03f7469..3ae0cbf 100644
--- a/chromeos/ui/base/window_state_type.cc
+++ b/chromeos/ui/base/window_state_type.cc
@@ -34,6 +34,8 @@
       return stream << "kTrustedPinned";
     case WindowStateType::kPip:
       return stream << "kPip";
+    case WindowStateType::kFloated:
+      return stream << "kFloated";
   }
 
   NOTREACHED();
@@ -69,6 +71,7 @@
     case WindowStateType::kPrimarySnapped:
     case WindowStateType::kAutoPositioned:
     case WindowStateType::kPip:
+    case WindowStateType::kFloated:
       return ui::SHOW_STATE_NORMAL;
 
     case WindowStateType::kMinimized:
diff --git a/chromeos/ui/base/window_state_type.h b/chromeos/ui/base/window_state_type.h
index a64dfb8e..a04337dc 100644
--- a/chromeos/ui/base/window_state_type.h
+++ b/chromeos/ui/base/window_state_type.h
@@ -44,6 +44,11 @@
 
   // A window in Picture-in-Picture mode (PIP).
   kPip,
+
+  // A window is floated on top of other windows (except PIP). When a window is
+  // floated, users are allowed to change the position and size of the window.
+  // One floated window is allowed per desk.
+  kFloated,
 };
 
 COMPONENT_EXPORT(CHROMEOS_UI_BASE)
diff --git a/chromeos/ui/wm/window_util.cc b/chromeos/ui/wm/window_util.cc
index 13decb2..8563ad04 100644
--- a/chromeos/ui/wm/window_util.cc
+++ b/chromeos/ui/wm/window_util.cc
@@ -12,8 +12,8 @@
 
 void ToggleFloating(aura::Window* window) {
   DCHECK(window);
-  const bool window_float_state = window->GetProperty(kWindowFloatTypeKey);
-  window->SetProperty(kWindowFloatTypeKey, !window_float_state);
+  const bool window_float_state = window->GetProperty(kWindowToggleFloatKey);
+  window->SetProperty(kWindowToggleFloatKey, !window_float_state);
 }
 
 }  // namespace chromeos
diff --git a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
index bdfb015f..5aa6ca0 100644
--- a/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
+++ b/components/autofill/core/browser/webdata/autofill_wallet_offer_sync_bridge.cc
@@ -204,7 +204,6 @@
   web_data_backend_->CommitChanges();
 
   if (offer_data_changed) {
-    // TODO(crbug.com/1112095): Add enum to indicate what actually changed.
     web_data_backend_->NotifyOfMultipleAutofillChanges();
   }
 }
diff --git a/components/browser_sync/sync_api_component_factory_impl.cc b/components/browser_sync/sync_api_component_factory_impl.cc
index 928e19cb..bd709095 100644
--- a/components/browser_sync/sync_api_component_factory_impl.cc
+++ b/components/browser_sync/sync_api_component_factory_impl.cc
@@ -222,8 +222,6 @@
 
     // Wallet offer data is enabled by default. Register unless explicitly
     // disabled.
-    // TODO(crbug.com/1112095): Currently the offer data depends on Wallet data
-    // sync, but revisit after other offer types are implemented.
     if (!disabled_types.Has(syncer::AUTOFILL_WALLET_DATA) &&
         !disabled_types.Has(syncer::AUTOFILL_WALLET_OFFER)) {
       controllers.push_back(CreateWalletModelTypeController(
diff --git a/components/desks_storage/core/desk_sync_bridge.cc b/components/desks_storage/core/desk_sync_bridge.cc
index 23483ac02..24da0bf 100644
--- a/components/desks_storage/core/desk_sync_bridge.cc
+++ b/components/desks_storage/core/desk_sync_bridge.cc
@@ -365,6 +365,8 @@
     case chromeos::WindowStateType::kPinned:
     case chromeos::WindowStateType::kTrustedPinned:
     case chromeos::WindowStateType::kPip:
+    // TODO(crbug.com/1331825): Float state support for desk template.
+    case chromeos::WindowStateType::kFloated:
       return WindowState::WorkspaceDeskSpecifics_WindowState_NORMAL;
     case chromeos::WindowStateType::kMinimized:
       return WindowState::WorkspaceDeskSpecifics_WindowState_MINIMIZED;
diff --git a/components/infobars/core/infobar_delegate.h b/components/infobars/core/infobar_delegate.h
index ae830e5..8717d40 100644
--- a/components/infobars/core/infobar_delegate.h
+++ b/components/infobars/core/infobar_delegate.h
@@ -180,6 +180,7 @@
     IOS_PERMISSIONS_INFOBAR_DELEGATE = 108,
     SUPPORTED_LINKS_INFOBAR_DELEGATE_CHROMEOS = 109,
     AUTOFILL_VIRTUAL_CARD_ENROLLMENT_INFOBAR_DELEGATE_MOBILE = 110,
+    BASIC_PRINT_DEPRECATED_ACCELERATOR_DELEGATE = 111,
   };
 
   // Describes navigation events, used to decide whether infobars should be
diff --git a/components/paint_preview/player/android/BUILD.gn b/components/paint_preview/player/android/BUILD.gn
index 8974933..f573976 100644
--- a/components/paint_preview/player/android/BUILD.gn
+++ b/components/paint_preview/player/android/BUILD.gn
@@ -145,9 +145,9 @@
     "//third_party/android_support_test_runner:rules_java",
     "//third_party/android_support_test_runner:runner_java",
     "//third_party/androidx:androidx_test_runner_java",
+    "//third_party/androidx:androidx_test_uiautomator_uiautomator_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
-    "//third_party/ub-uiautomator:ub_uiautomator_java",
     "//ui/android:ui_java_test_support",
     "//url:gurl_java",
   ]
diff --git a/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java b/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
index 2b335aba..40133c3 100644
--- a/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
+++ b/components/paint_preview/player/android/javatests/src/org/chromium/components/paintpreview/player/PaintPreviewPlayerTest.java
@@ -8,14 +8,14 @@
 import android.os.Build;
 import android.os.Build.VERSION_CODES;
 import android.support.test.InstrumentationRegistry;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject2;
 import android.util.Size;
 import android.view.View;
 import android.view.ViewGroup;
 
 import androidx.test.filters.MediumTest;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
 
 import org.hamcrest.Matchers;
 import org.junit.Assert;
diff --git a/components/reporting/storage/storage_queue.cc b/components/reporting/storage/storage_queue.cc
index dce572d6..d2e9af5 100644
--- a/components/reporting/storage/storage_queue.cc
+++ b/components/reporting/storage/storage_queue.cc
@@ -317,8 +317,8 @@
       options_.directory(),
       /*recursive=*/false, base::FileEnumerator::FILES,
       base::StrCat({options_.file_prefix(), FILE_PATH_LITERAL(".*")}));
-  base::FilePath full_name;
-  while (full_name = dir_enum.Next(), !full_name.empty()) {
+  for (auto full_name = dir_enum.Next(); !full_name.empty();
+       full_name = dir_enum.Next()) {
     const auto file_sequencing_id_result =
         AddDataFile(full_name, dir_enum.GetInfo());
     if (!file_sequencing_id_result.ok()) {
diff --git a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
index 7251778..052ea0f 100644
--- a/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
+++ b/components/safe_browsing/content/browser/web_ui/safe_browsing_ui.cc
@@ -1029,6 +1029,8 @@
     dict.SetBoolean("is_phishing", cpr.is_phishing());
   if (cpr.has_model_version())
     dict.SetInteger("model_version", cpr.model_version());
+  if (cpr.has_dom_model_version())
+    dict.SetInteger("dom_model_version", cpr.dom_model_version());
 
   base::Value::ListStorage features;
   for (const auto& feature : cpr.feature_map()) {
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
index a2a1ee9..0e8954fdc 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.cc
@@ -205,6 +205,10 @@
   return flatbuffer_model_->version();
 }
 
+int FlatBufferModelScorer::dom_model_version() const {
+  return flatbuffer_model_->dom_model_version();
+}
+
 bool FlatBufferModelScorer::has_page_term(const std::string& str) const {
   const flatbuffers::Vector<flatbuffers::Offset<flat::Hash>>* hashes =
       flatbuffer_model_->hashes();
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
index a81c1a1..a34974a 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/flatbuffer_scorer.h
@@ -56,6 +56,7 @@
 #endif
 
   int model_version() const override;
+  int dom_model_version() const override;
   size_t max_words_per_term() const override;
   uint32_t murmurhash3_seed() const override;
   size_t max_shingles_per_page() const override;
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
index 9c03565..c382b71 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/phishing_classifier.cc
@@ -272,6 +272,7 @@
   std::unique_ptr<ClientPhishingRequest> verdict =
       std::make_unique<ClientPhishingRequest>();
   verdict->set_model_version(scorer->model_version());
+  verdict->set_dom_model_version(scorer->dom_model_version());
   verdict->set_url(main_frame->GetDocument().Url().GetString().Utf8());
   for (const auto& it : features_->features()) {
     bool result = hashed_features.AddRealFeature(
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
index 48a3314..1ca421ec 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.cc
@@ -127,6 +127,10 @@
   return model_.version();
 }
 
+int ProtobufModelScorer::dom_model_version() const {
+  return model_.dom_model_version();
+}
+
 bool Scorer::HasVisualTfLiteModel() const {
   return visual_tflite_model_.IsValid();
 }
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
index 0a6bf37e..4243d3ee 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/protobuf_scorer.h
@@ -54,6 +54,7 @@
 #endif
 
   int model_version() const override;
+  int dom_model_version() const override;
   base::RepeatingCallback<bool(uint32_t)> find_page_word_callback()
       const override;
   base::RepeatingCallback<bool(const std::string&)> find_page_term_callback()
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
index d33e394..1461ed2 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.h
@@ -81,6 +81,8 @@
   // Returns the version number of the loaded client model.
   virtual int model_version() const = 0;
 
+  virtual int dom_model_version() const = 0;
+
   bool HasVisualTfLiteModel() const;
 
   // -- Accessors used by the page feature extractor ---------------------------
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
index 2bbb8af..7dcd9f3 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer_unittest.cc
@@ -84,6 +84,7 @@
   csd_model_builder.add_max_shingles_per_page(10);
   csd_model_builder.add_shingle_size(3);
   csd_model_builder.add_tflite_metadata(tflite_metadata_flat);
+  csd_model_builder.add_dom_model_version(123);
 
   builder.Finish(csd_model_builder.Finish());
   return std::string(reinterpret_cast<char*>(builder.GetBufferPointer()),
@@ -139,6 +140,7 @@
     model_.set_murmur_hash_seed(12345U);
     model_.set_max_shingles_per_page(10);
     model_.set_shingle_size(3);
+    model_.set_dom_model_version(123);
   }
 
   void TearDown() override {
@@ -348,4 +350,23 @@
   EXPECT_DOUBLE_EQ(0.77729986117469119, scorer->ComputeScore(features));
 }
 
+TEST_F(PhishingScorerTest, DomModelVersionProtobuffer) {
+  std::unique_ptr<Scorer> scorer;
+  scorer =
+      ProtobufModelScorer::Create(model_.SerializeAsString(), base::File());
+  ASSERT_TRUE(scorer.get() != nullptr);
+  EXPECT_EQ(scorer->dom_model_version(), 123);
+}
+
+TEST_F(PhishingScorerTest, DomModelVersionFlatbuffer) {
+  std::unique_ptr<Scorer> scorer;
+  std::string flatbuffer = GetFlatBufferString();
+  base::MappedReadOnlyRegion mapped_region =
+      GetMappedReadOnlyRegionWithData(flatbuffer);
+  scorer = FlatBufferModelScorer::Create(mapped_region.region.Duplicate(),
+                                         base::File());
+  ASSERT_TRUE(scorer.get() != nullptr);
+  EXPECT_EQ(scorer->dom_model_version(), 123);
+}
+
 }  // namespace safe_browsing
diff --git a/components/safe_browsing/core/common/fbs/client_model.fbs b/components/safe_browsing/core/common/fbs/client_model.fbs
index 2cc0998..7bb1c2272 100644
--- a/components/safe_browsing/core/common/fbs/client_model.fbs
+++ b/components/safe_browsing/core/common/fbs/client_model.fbs
@@ -39,6 +39,7 @@
   tflite_model_input_width: int (deprecated);
   tflite_model_input_height: int (deprecated);
   tflite_metadata:safe_browsing.flat.TfLiteModelMetadata;
+  dom_model_version:int;
 }
 
 root_type ClientSideModel;
diff --git a/components/safe_browsing/core/common/proto/client_model.proto b/components/safe_browsing/core/common/proto/client_model.proto
index 3c74599e..920711a57 100644
--- a/components/safe_browsing/core/common/proto/client_model.proto
+++ b/components/safe_browsing/core/common/proto/client_model.proto
@@ -70,9 +70,11 @@
   // Page terms in page_term contain at most this many page words.
   required int32 max_words_per_term = 5;
 
-  // Model version number.  Every model that we train should have a different
-  // version number and it should always be larger than the previous model
-  // version.
+  optional int32 dom_model_version = 18;
+
+  // The overall client model version number.  Every model update should have a
+  // different version number and it should always be larger than the previous
+  // model version.
   optional int32 version = 6;
 
   // List of known bad IP subnets.
@@ -107,7 +109,7 @@
 
   optional TfLiteModelMetadata tflite_metadata = 17;
 
-  // next available tag number: 18
+  // next available tag number: 19
 }
 
 message TfLiteModelMetadata {
diff --git a/components/safe_browsing/core/common/proto/csd.proto b/components/safe_browsing/core/common/proto/csd.proto
index 34e9e613..4112daa 100644
--- a/components/safe_browsing/core/common/proto/csd.proto
+++ b/components/safe_browsing/core/common/proto/csd.proto
@@ -160,6 +160,9 @@
   // sent to the scorer and which resulted in client_score being computed.
   repeated Feature feature_map = 5;
 
+  // The version of the DOM model used for classification
+  optional int32 dom_model_version = 27;
+
   // The version number of the model that was used to compute the client-score.
   // Copied from ClientSideModel.version().
   optional int32 model_version = 6;
@@ -227,7 +230,7 @@
   // users.
   optional VisualFeatures visual_features = 26;
 
-  // next available tag number: 27.
+  // next available tag number: 28.
 }
 
 message ClientPhishingResponse {
diff --git a/components/sessions/core/live_tab_context.h b/components/sessions/core/live_tab_context.h
index fff5e758..db697a8 100644
--- a/components/sessions/core/live_tab_context.h
+++ b/components/sessions/core/live_tab_context.h
@@ -36,6 +36,7 @@
   // TODO(blundell): Rename.
   virtual void ShowBrowserWindow() = 0;
   virtual SessionID GetSessionID() const = 0;
+  virtual SessionWindow::WindowType GetWindowType() const = 0;
   virtual int GetTabCount() const = 0;
   virtual int GetSelectedIndex() const = 0;
   virtual std::string GetAppName() const = 0;
diff --git a/components/sessions/core/tab_restore_service.h b/components/sessions/core/tab_restore_service.h
index 80a2722..5e7ecb5 100644
--- a/components/sessions/core/tab_restore_service.h
+++ b/components/sessions/core/tab_restore_service.h
@@ -146,6 +146,9 @@
     // Entry:
     size_t EstimateMemoryUsage() const override;
 
+    // Type of window.
+    SessionWindow::WindowType type;
+
     // The tabs that comprised the window, in order.
     std::vector<std::unique_ptr<Tab>> tabs;
 
diff --git a/components/sessions/core/tab_restore_service_client.h b/components/sessions/core/tab_restore_service_client.h
index 9d9c10c8..029b9ca0 100644
--- a/components/sessions/core/tab_restore_service_client.h
+++ b/components/sessions/core/tab_restore_service_client.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "components/sessions/core/session_id.h"
+#include "components/sessions/core/session_types.h"
 #include "components/sessions/core/sessions_export.h"
 #include "ui/base/ui_base_types.h"
 
@@ -28,7 +29,6 @@
 
 class LiveTab;
 class LiveTabContext;
-struct SessionWindow;
 
 // Callback from TabRestoreServiceClient::GetLastSession.
 // The second parameter is the id of the window that was last active.
@@ -47,6 +47,7 @@
   // functionality).
   virtual LiveTabContext* CreateLiveTabContext(
       LiveTabContext* existing_context,
+      SessionWindow::WindowType type,
       const std::string& app_name,
       const gfx::Rect& bounds,
       ui::WindowShowState show_state,
diff --git a/components/sessions/core/tab_restore_service_helper.cc b/components/sessions/core/tab_restore_service_helper.cc
index d946a538..aa7c9c3 100644
--- a/components/sessions/core/tab_restore_service_helper.cc
+++ b/components/sessions/core/tab_restore_service_helper.cc
@@ -193,6 +193,7 @@
   closing_contexts_.insert(context);
 
   auto window = std::make_unique<Window>();
+  window->type = context->GetWindowType();
   window->selected_tab_index = context->GetSelectedIndex();
   window->timestamp = TimeNow();
   window->app_name = context->GetAppName();
@@ -489,8 +490,9 @@
       // restored.
       if (entry_id_matches_restore_id || !window.app_name.empty()) {
         context = client_->CreateLiveTabContext(
-            context, window.app_name, window.bounds, window.show_state,
-            window.workspace, window.user_title, window.extra_data);
+            context, window.type, window.app_name, window.bounds,
+            window.show_state, window.workspace, window.user_title,
+            window.extra_data);
 
         base::flat_map<tab_groups::TabGroupId, tab_groups::TabGroupId>
             new_group_ids;
@@ -878,8 +880,9 @@
       tab_index = tab.tabstrip_index;
     } else {
       context = client_->CreateLiveTabContext(
-          context, std::string(), gfx::Rect(), ui::SHOW_STATE_NORMAL,
-          std::string(), std::string(), std::map<std::string, std::string>());
+          context, SessionWindow::TYPE_NORMAL, std::string(), gfx::Rect(),
+          ui::SHOW_STATE_NORMAL, std::string(), std::string(),
+          std::map<std::string, std::string>());
       if (tab.browser_id)
         UpdateTabBrowserIDs(tab.browser_id, context->GetSessionID());
     }
diff --git a/components/sessions/core/tab_restore_service_impl.cc b/components/sessions/core/tab_restore_service_impl.cc
index 7c7f7f9b..35f2ba5 100644
--- a/components/sessions/core/tab_restore_service_impl.cc
+++ b/components/sessions/core/tab_restore_service_impl.cc
@@ -238,6 +238,24 @@
   return false;
 }
 
+// Converts an int to a window type. Returns true on success, false otherwise.
+bool DeserializeWindowType(int type_int,
+                           sessions::SessionWindow::WindowType* type) {
+  switch (static_cast<sessions::SessionWindow::WindowType>(type_int)) {
+    case sessions::SessionWindow::TYPE_NORMAL:
+    case sessions::SessionWindow::TYPE_POPUP:
+    case sessions::SessionWindow::TYPE_APP:
+    case sessions::SessionWindow::TYPE_DEVTOOLS:
+    case sessions::SessionWindow::TYPE_APP_POPUP:
+#if BUILDFLAG(IS_CHROMEOS_ASH)
+    case sessions::SessionWindow::TYPE_CUSTOM_TAB:
+#endif
+      *type = static_cast<sessions::SessionWindow::WindowType>(type_int);
+      return true;
+  }
+  return false;
+}
+
 // Superset of WindowPayloadObsolete/WindowPayloadObsolete2 and the other fields
 // that can appear in the Pickle version of a Window command. This is used as a
 // convenient destination for parsing the various fields in a WindowCommand.
@@ -259,6 +277,8 @@
   int window_height = 0;
   int window_show_state = 0;
   std::string workspace;
+
+  int type = 0;
 };
 
 std::unique_ptr<sessions::TabRestoreService::Window>
@@ -267,6 +287,7 @@
                              int32_t* num_tabs) {
   WindowCommandFields fields;
   ui::WindowShowState show_state = ui::SHOW_STATE_DEFAULT;
+  auto type = sessions::SessionWindow::TYPE_NORMAL;
 
   if (command->id() == kCommandWindow) {
     std::unique_ptr<base::Pickle> pickle(command->PayloadAsPickle());
@@ -291,6 +312,14 @@
       return nullptr;
     }
 
+    // New field in M104, use default if it fails to read.
+    // TODO(crbug.com/1332968): After some time (say M114), this code can be
+    // added into parsing above which fails when ReadInt() fails.
+    if (!it.ReadInt(&parsed_fields.type)) {
+      parsed_fields.type =
+          static_cast<int>(sessions::SessionWindow::TYPE_NORMAL);
+    }
+
     // Validate the parameters. If the entire pickles parses but any of the
     // validation fails assume corruption.
     if (parsed_fields.window_width < 0 || parsed_fields.window_height < 0)
@@ -302,6 +331,10 @@
       return nullptr;
     }
 
+    // Validate window type.
+    if (!DeserializeWindowType(parsed_fields.type, &type)) {
+      return nullptr;
+    }
     // New fields added to the pickle in later versions would be parsed and
     // validated here.
 
@@ -346,6 +379,7 @@
   // Create the Window entry.
   std::unique_ptr<sessions::TabRestoreService::Window> window =
       std::make_unique<sessions::TabRestoreService::Window>();
+  window->type = type;
   window->selected_tab_index = fields.selected_tab_index;
   window->timestamp = base::Time::FromDeltaSinceWindowsEpoch(
       base::Microseconds(fields.timestamp));
@@ -489,6 +523,7 @@
   // Creates a window close command.
   static std::unique_ptr<SessionCommand> CreateWindowCommand(
       SessionID window_id,
+      SessionWindow::WindowType type,
       int selected_tab_index,
       int num_tabs,
       const gfx::Rect& bounds,
@@ -764,7 +799,7 @@
     return;  // No tabs to persist.
 
   command_storage_manager_->ScheduleCommand(CreateWindowCommand(
-      window.id, std::min(real_selected_tab, valid_tab_count - 1),
+      window.id, window.type, std::min(real_selected_tab, valid_tab_count - 1),
       valid_tab_count, window.bounds, window.show_state, window.workspace,
       window.timestamp));
 
@@ -874,6 +909,7 @@
 std::unique_ptr<SessionCommand>
 TabRestoreServiceImpl::PersistenceDelegate::CreateWindowCommand(
     SessionID window_id,
+    SessionWindow::WindowType type,
     int selected_tab_index,
     int num_tabs,
     const gfx::Rect& bounds,
@@ -903,6 +939,8 @@
   else
     pickle.WriteString(std::string());
 
+  pickle.WriteInt(type);
+
   std::unique_ptr<SessionCommand> command(
       new SessionCommand(kCommandWindow, pickle));
   return command;
@@ -1335,6 +1373,8 @@
 bool TabRestoreServiceImpl::PersistenceDelegate::ConvertSessionWindowToWindow(
     SessionWindow* session_window,
     Window* window) {
+  window->type = session_window->type;
+
   // The group visual datas must be stored in both |window| and each
   // grouped tab.
   std::map<tab_groups::TabGroupId, tab_groups::TabGroupVisualData>
diff --git a/components/viz/README.md b/components/viz/README.md
index d6a63a63..1170d45 100644
--- a/components/viz/README.md
+++ b/components/viz/README.md
@@ -131,13 +131,6 @@
 compositor (typically thought of as SwapBuffers), as well as the use of
 overlays.
 
-The source code is split into two build targets,
-``components/viz/service:service`` and
-``components/viz/service:gpu_service_dependencies``. The latter is
-code that requires being run in the gpu process, thus could not work
-if the viz service is located elsewhere. This is forward-looking code
-as the viz service is moving into the gpu process always.
-
 | Can depend on:                        |
 |:--------------------------------------|
 | viz/common/*                          |
@@ -187,12 +180,6 @@
 deallocating) gpu memory buffers, setting up a channel for the command buffer,
 etc.
 
-Similar to ``service/display_embedder`` this is split into two targets in
-the build system. Code that must run in the gpu process is compiled in
-the ``components/viz/service:gpu_service_dependencies`` build target,
-and the rest is compiled in ``components/viz/service:service``. As all
-code moves to the gpu process, these two build targets will merge.
-
 | Can depend on:        |
 |:----------------------|
 | viz/common/*          |
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index 33e1f40f..10d10f49 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -39,6 +39,8 @@
     "display/display.cc",
     "display/display.h",
     "display/display_client.h",
+    "display/display_compositor_memory_and_task_controller.cc",
+    "display/display_compositor_memory_and_task_controller.h",
     "display/display_damage_tracker.cc",
     "display/display_damage_tracker.h",
     "display/display_resource_provider.cc",
@@ -98,13 +100,38 @@
     "display_embedder/buffer_queue.h",
     "display_embedder/compositor_gpu_thread.cc",
     "display_embedder/compositor_gpu_thread.h",
+    "display_embedder/image_context_impl.cc",
+    "display_embedder/image_context_impl.h",
     "display_embedder/in_process_gpu_memory_buffer_manager.cc",
     "display_embedder/in_process_gpu_memory_buffer_manager.h",
+    "display_embedder/output_presenter.cc",
+    "display_embedder/output_presenter.h",
+    "display_embedder/output_presenter_gl.cc",
+    "display_embedder/output_presenter_gl.h",
     "display_embedder/output_surface_provider.h",
     "display_embedder/output_surface_provider_impl.cc",
     "display_embedder/output_surface_provider_impl.h",
     "display_embedder/server_shared_bitmap_manager.cc",
     "display_embedder/server_shared_bitmap_manager.h",
+    "display_embedder/skia_output_device.cc",
+    "display_embedder/skia_output_device.h",
+    "display_embedder/skia_output_device_buffer_queue.cc",
+    "display_embedder/skia_output_device_buffer_queue.h",
+    "display_embedder/skia_output_device_gl.cc",
+    "display_embedder/skia_output_device_gl.h",
+    "display_embedder/skia_output_device_offscreen.cc",
+    "display_embedder/skia_output_device_offscreen.h",
+    "display_embedder/skia_output_device_webview.cc",
+    "display_embedder/skia_output_device_webview.h",
+    "display_embedder/skia_output_surface_dependency.h",
+    "display_embedder/skia_output_surface_dependency_impl.cc",
+    "display_embedder/skia_output_surface_dependency_impl.h",
+    "display_embedder/skia_output_surface_impl.cc",
+    "display_embedder/skia_output_surface_impl.h",
+    "display_embedder/skia_output_surface_impl_on_gpu.cc",
+    "display_embedder/skia_output_surface_impl_on_gpu.h",
+    "display_embedder/skia_render_copy_results.cc",
+    "display_embedder/skia_render_copy_results.h",
     "display_embedder/software_output_surface.cc",
     "display_embedder/software_output_surface.h",
     "display_embedder/vsync_parameter_listener.cc",
@@ -148,6 +175,8 @@
     "frame_sinks/video_capture/video_frame_pool.h",
     "frame_sinks/video_detector.cc",
     "frame_sinks/video_detector.h",
+    "gl/gpu_service_impl.cc",
+    "gl/gpu_service_impl.h",
     "hit_test/hit_test_aggregator.cc",
     "hit_test/hit_test_aggregator.h",
     "hit_test/hit_test_aggregator_delegate.h",
@@ -189,8 +218,6 @@
 
   defines = [ "VIZ_SERVICE_IMPLEMENTATION" ]
 
-  allow_circular_includes_from = [ ":gpu_service_dependencies" ]
-
   deps = [
     "//build:chromecast_buildflags",
     "//build:chromeos_buildflags",
@@ -198,13 +225,12 @@
     "//cc/paint",
     "//components/crash/core/common:crash_key",
     "//components/power_scheduler",
-    "//gpu/command_buffer/client:gles2_cmd_helper",
-    "//gpu/command_buffer/client:gles2_implementation",
-    "//gpu/command_buffer/client:raster",
 
     # Note that dependency on //gpu/ipc/client is for GpuMemoryBufferImpl. This
     # dependency should not be in public_deps.
     "//components/viz/common",
+    "//gpu/command_buffer/client",
+    "//gpu/config",
     "//gpu/ipc/client",
     "//gpu/ipc/common:common",
     "//gpu/ipc/common:surface_handle_type",
@@ -224,14 +250,20 @@
   ]
 
   public_deps = [
-    ":gpu_service_dependencies",
     "//base",
     "//cc",
     "//cc/debug",
     "//components/viz/common",
-    "//gpu/command_buffer/client:gles2_interface",
+    "//gpu/command_buffer/service:gles2",
+    "//gpu/ipc:gl_in_process_context",
+    "//gpu/ipc/service",
+    "//gpu/vulkan:buildflags",
+    "//media/gpu/ipc/service",
+    "//media/mojo/services",
     "//services/viz/privileged/mojom/compositing",
+    "//services/viz/privileged/mojom/gl",
     "//services/viz/public/mojom",
+    "//skia",
     "//ui/base/prediction",
     "//ui/gfx",
     "//ui/gfx/geometry",
@@ -239,6 +271,18 @@
   ]
 
   if (is_chromeos_ash) {
+    sources += [
+      "display_embedder/output_surface_unified.cc",
+      "display_embedder/output_surface_unified.h",
+    ]
+
+    deps += [
+      "//components/chromeos_camera:jpeg_encode_accelerator_service",
+      "//components/chromeos_camera:mjpeg_decode_accelerator_service",
+      "//gpu/command_buffer/service:gles2",
+      "//media/mojo/services",
+    ]
+
     if (use_v4l2_codec || use_vaapi) {
       deps += [ "//ash/components/arc/video_accelerator" ]
     }
@@ -325,85 +369,6 @@
       "display_embedder/output_device_backing.h",
       "display_embedder/software_output_device_win.cc",
       "display_embedder/software_output_device_win.h",
-    ]
-  }
-
-  if (is_chromeos_ash) {
-    sources += [
-      "display_embedder/output_surface_unified.cc",
-      "display_embedder/output_surface_unified.h",
-    ]
-  }
-
-  if (enable_vulkan) {
-    deps += [ "//gpu/vulkan" ]
-  }
-}
-
-# The gpu_service_dependencies source set contains source files that
-# use the service side GL library (ui/gl), while the rest of
-# viz/service use the client side GL library. This split is needed
-# because the two GL libraries are incompatible and can't compile
-# together in jumbo builds.
-#
-# Long term all service code is moving to be in the gpu process and
-# then this build target will no longer be needed.
-viz_source_set("gpu_service_dependencies") {
-  sources = [
-    "display/display_compositor_memory_and_task_controller.cc",
-    "display/display_compositor_memory_and_task_controller.h",
-    "display_embedder/image_context_impl.cc",
-    "display_embedder/image_context_impl.h",
-    "display_embedder/output_presenter.cc",
-    "display_embedder/output_presenter.h",
-    "display_embedder/output_presenter_gl.cc",
-    "display_embedder/output_presenter_gl.h",
-    "display_embedder/skia_output_device.cc",
-    "display_embedder/skia_output_device.h",
-    "display_embedder/skia_output_device_buffer_queue.cc",
-    "display_embedder/skia_output_device_buffer_queue.h",
-    "display_embedder/skia_output_device_gl.cc",
-    "display_embedder/skia_output_device_gl.h",
-    "display_embedder/skia_output_device_offscreen.cc",
-    "display_embedder/skia_output_device_offscreen.h",
-    "display_embedder/skia_output_device_webview.cc",
-    "display_embedder/skia_output_device_webview.h",
-    "display_embedder/skia_output_surface_dependency.h",
-    "display_embedder/skia_output_surface_dependency_impl.cc",
-    "display_embedder/skia_output_surface_dependency_impl.h",
-    "display_embedder/skia_output_surface_impl.cc",
-    "display_embedder/skia_output_surface_impl.h",
-    "display_embedder/skia_output_surface_impl_on_gpu.cc",
-    "display_embedder/skia_output_surface_impl_on_gpu.h",
-    "display_embedder/skia_render_copy_results.cc",
-    "display_embedder/skia_render_copy_results.h",
-    "gl/gpu_service_impl.cc",
-    "gl/gpu_service_impl.h",
-  ]
-
-  public_deps = [
-    "//gpu/command_buffer/service:gles2",
-    "//gpu/ipc:gl_in_process_context",
-    "//gpu/ipc/service",
-    "//gpu/vulkan:buildflags",
-    "//media/gpu/ipc/service",
-    "//media/mojo/services",
-    "//services/viz/privileged/mojom/gl",
-    "//skia",
-    "//ui/latency:latency",
-  ]
-
-  defines = [ "VIZ_SERVICE_IMPLEMENTATION" ]
-
-  deps = [
-    "//base",
-    "//build:chromeos_buildflags",
-    "//gpu/config",
-    "//third_party/libyuv",
-  ]
-
-  if (is_win) {
-    sources += [
       "gl/info_collection_gpu_service_impl.cc",
       "gl/info_collection_gpu_service_impl.h",
     ]
@@ -419,34 +384,25 @@
     ]
   }
 
-  if (is_chromeos_ash) {
-    deps += [
-      "//components/chromeos_camera:jpeg_encode_accelerator_service",
-      "//components/chromeos_camera:mjpeg_decode_accelerator_service",
-      "//gpu/command_buffer/service:gles2",
-      "//media/mojo/services",
+  if (is_fuchsia) {
+    sources += [
+      "display_embedder/output_presenter_fuchsia.cc",
+      "display_embedder/output_presenter_fuchsia.h",
     ]
-    if (use_v4l2_codec || use_vaapi) {
-      deps += [ "//ash/components/arc/video_accelerator" ]
-    }
   }
 
   if (use_vaapi) {
     deps += [ "//media/gpu/vaapi" ]
   }
 
-  if (use_ozone) {
-    deps += [ "//ui/ozone" ]
-  }
-
   if (enable_vulkan) {
+    deps += [ "//gpu/vulkan" ]
+
     sources += [
       "display_embedder/skia_output_device_vulkan.cc",
       "display_embedder/skia_output_device_vulkan.h",
     ]
 
-    public_deps += [ "//gpu/vulkan" ]
-
     if (is_android) {
       sources += [
         "display_embedder/skia_output_device_vulkan_secondary_cb.cc",
@@ -486,13 +442,6 @@
       "//third_party/dawn/src/dawn/native",
     ]
   }
-
-  if (is_fuchsia) {
-    sources += [
-      "display_embedder/output_presenter_fuchsia.cc",
-      "display_embedder/output_presenter_fuchsia.h",
-    ]
-  }
 }
 
 viz_source_set("unit_tests") {
@@ -564,7 +513,6 @@
     "//components/viz/test:test_suite",
     "//components/viz/test:test_support",
     "//gpu/command_buffer/client",
-    "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/ipc:gl_in_process_context",
     "//gpu/ipc/service",
     "//media",
diff --git a/components/viz/service/display/DEPS b/components/viz/service/display/DEPS
index 057df66329..ca3f9db 100644
--- a/components/viz/service/display/DEPS
+++ b/components/viz/service/display/DEPS
@@ -16,7 +16,7 @@
   "+components/viz/service/display_embedder/overlay_candidate_validator_win.h",
   "+components/viz/service/display_embedder/skia_output_surface_dependency.h",
   "+components/viz/common",
-  "+gpu/command_buffer/client",
+  "+gpu/command_buffer/client/shared_image_interface.h",
   "+gpu/command_buffer/common",
   "+gpu/command_buffer/service",
   "+gpu/GLES2",
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 66657ef..07d38ad 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -48,8 +48,6 @@
 #include "components/viz/service/display/surface_aggregator.h"
 #include "components/viz/service/surfaces/surface.h"
 #include "components/viz/service/surfaces/surface_manager.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/ipc/scheduler_sequence.h"
 #include "services/viz/public/mojom/compositing/compositor_frame_sink.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
diff --git a/components/viz/service/display/output_surface.cc b/components/viz/service/display/output_surface.cc
index 9354f7d..643a191 100644
--- a/components/viz/service/display/output_surface.cc
+++ b/components/viz/service/display/output_surface.cc
@@ -15,8 +15,6 @@
 #include "components/viz/service/display/output_surface_client.h"
 #include "components/viz/service/display/output_surface_frame.h"
 #include "gpu/GLES2/gl2extchromium.h"
-#include "gpu/command_buffer/client/context_support.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/swap_result.h"
 
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 22af7c5..32312f8 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -45,7 +45,6 @@
 #include "components/viz/test/test_in_process_context_provider.h"
 #include "components/viz/test/test_shared_bitmap_manager.h"
 #include "components/viz/test/test_types.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "media/base/video_frame.h"
@@ -61,8 +60,6 @@
 #include "ui/gfx/geometry/mask_filter_info.h"
 #include "ui/gfx/test/icc_profiles.h"
 
-using gpu::gles2::GLES2Interface;
-
 namespace viz {
 namespace {
 
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index fbd06e7..7d5298d 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -45,7 +45,6 @@
 #include "components/viz/service/display/renderer_utils.h"
 #include "components/viz/service/display/resource_fence.h"
 #include "components/viz/service/display/skia_output_surface.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/common/sync_token.h"
diff --git a/components/viz/service/display_embedder/DEPS b/components/viz/service/display_embedder/DEPS
index 6f48eb9..c8b25c2 100644
--- a/components/viz/service/display_embedder/DEPS
+++ b/components/viz/service/display_embedder/DEPS
@@ -19,7 +19,9 @@
   "+components/viz/service/display/skia_output_surface.h",
   "+components/viz/service/display/software_output_device.h",
   "+components/viz/service/gl/gpu_service_impl.h",
-  "+gpu/command_buffer/client",
+  "+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
+  "+gpu/command_buffer/client/shared_image_interface.h",
+  "+gpu/command_buffer/client/shared_memory_limits.h",
   "+gpu/command_buffer/common",
   "+gpu/command_buffer/service",
   "+gpu/config",
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index a8e80937a9..0f9b617 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -38,7 +38,6 @@
 #include "gpu/ipc/common/gpu_memory_buffer_support.h"
 #include "gpu/ipc/common/gpu_peak_memory.h"
 #include "gpu/ipc/common/memory_stats.h"
-#include "gpu/ipc/in_process_command_buffer.h"
 #include "gpu/ipc/service/gpu_channel.h"
 #include "gpu/ipc/service/gpu_channel_manager.h"
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
diff --git a/components/viz/service/main/viz_compositor_thread_runner_impl.cc b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
index 4ae77f1..6b7d8fc 100644
--- a/components/viz/service/main/viz_compositor_thread_runner_impl.cc
+++ b/components/viz/service/main/viz_compositor_thread_runner_impl.cc
@@ -28,7 +28,6 @@
 #include "components/viz/service/performance_hint/hint_session.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/config/gpu_switches.h"
-#include "gpu/ipc/command_buffer_task_executor.h"
 #include "gpu/ipc/scheduler_sequence.h"
 #include "gpu/ipc/service/gpu_memory_buffer_factory.h"
 #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 0dee896..481a733 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -146,7 +146,6 @@
     "//gpu/command_buffer/client:gles2_implementation",
     "//gpu/command_buffer/client:gles2_interface",
     "//gpu/command_buffer/client:raster_interface",
-    "//gpu/ipc:gl_in_process_context",
     "//gpu/ipc/host",
     "//gpu/vulkan:buildflags",
     "//media",
diff --git a/content/browser/aggregation_service/aggregatable_report.cc b/content/browser/aggregation_service/aggregatable_report.cc
index 4fc4c13..b6930322 100644
--- a/content/browser/aggregation_service/aggregatable_report.cc
+++ b/content/browser/aggregation_service/aggregatable_report.cc
@@ -22,6 +22,7 @@
 #include "base/rand_util.h"
 #include "base/ranges/algorithm.h"
 #include "base/strings/abseil_string_number_conversions.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
@@ -208,9 +209,9 @@
 // Encrypts the `plaintext` with HPKE using the processing url's
 // `public_key`. Returns empty vector if the encryption fails.
 std::vector<uint8_t> EncryptWithHpke(
-    const std::vector<uint8_t>& plaintext,
-    const std::vector<uint8_t>& public_key,
-    const std::vector<uint8_t>& authenticated_info) {
+    base::span<const uint8_t> plaintext,
+    base::span<const uint8_t> public_key,
+    base::span<const uint8_t> authenticated_info) {
   bssl::ScopedEVP_HPKE_CTX sender_context;
 
   // This vector will hold the encapsulated shared secret "enc" followed by the
@@ -505,18 +506,13 @@
     return absl::nullopt;
   }
 
-  std::vector<uint8_t> authenticated_info(kDomainSeparationPrefix.begin(),
-                                          kDomainSeparationPrefix.end());
-
-  // No null terminator should have been copied.
-  DCHECK(!authenticated_info.empty());
-  DCHECK_NE(authenticated_info.back(), 0);
-
   std::string encoded_shared_info =
       report_request.shared_info().SerializeAsJson();
-  authenticated_info.insert(authenticated_info.end(),
-                            encoded_shared_info.begin(),
-                            encoded_shared_info.end());
+
+  std::string authenticated_info_str =
+      base::StrCat({kDomainSeparationPrefix, encoded_shared_info});
+  base::span<const uint8_t> authenticated_info =
+      base::as_bytes(base::make_span(authenticated_info_str));
 
   std::vector<AggregatableReport::AggregationServicePayload> encrypted_payloads;
   DCHECK_EQ(unencrypted_payloads.size(), num_processing_urls);
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.cc b/content/browser/aggregation_service/aggregation_service_test_utils.cc
index 9d057b9f..8d2de6e 100644
--- a/content/browser/aggregation_service/aggregation_service_test_utils.cc
+++ b/content/browser/aggregation_service/aggregation_service_test_utils.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/base64.h"
+#include "base/check.h"
 #include "base/containers/contains.h"
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
@@ -302,18 +303,19 @@
 }
 
 std::vector<uint8_t> DecryptPayloadWithHpke(
-    const std::vector<uint8_t>& payload,
+    base::span<const uint8_t> payload,
     const EVP_HPKE_KEY& key,
     const std::string& expected_serialized_shared_info) {
-  base::span<const uint8_t> enc =
-      base::make_span(payload).subspan(0, X25519_PUBLIC_VALUE_LEN);
+  base::span<const uint8_t> enc = payload.subspan(0, X25519_PUBLIC_VALUE_LEN);
 
-  std::vector<uint8_t> authenticated_info(
-      AggregatableReport::kDomainSeparationPrefix.begin(),
-      AggregatableReport::kDomainSeparationPrefix.end());
-  authenticated_info.insert(authenticated_info.end(),
-                            expected_serialized_shared_info.begin(),
-                            expected_serialized_shared_info.end());
+  std::string authenticated_info_str =
+      base::StrCat({AggregatableReport::kDomainSeparationPrefix,
+                    expected_serialized_shared_info});
+  base::span<const uint8_t> authenticated_info =
+      base::as_bytes(base::make_span(authenticated_info_str));
+
+  // No null terminators should have been copied when concatenating the strings.
+  DCHECK(!base::Contains(authenticated_info_str, '\0'));
 
   bssl::ScopedEVP_HPKE_CTX recipient_context;
   if (!EVP_HPKE_CTX_setup_recipient(
@@ -327,7 +329,7 @@
   }
 
   base::span<const uint8_t> ciphertext =
-      base::make_span(payload).subspan(X25519_PUBLIC_VALUE_LEN);
+      payload.subspan(X25519_PUBLIC_VALUE_LEN);
   std::vector<uint8_t> plaintext(ciphertext.size());
   size_t plaintext_len;
 
diff --git a/content/browser/aggregation_service/aggregation_service_test_utils.h b/content/browser/aggregation_service/aggregation_service_test_utils.h
index ccb03f9..33d9249 100644
--- a/content/browser/aggregation_service/aggregation_service_test_utils.h
+++ b/content/browser/aggregation_service/aggregation_service_test_utils.h
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 
+#include "base/containers/span.h"
 #include "base/threading/sequence_bound.h"
 #include "content/browser/aggregation_service/aggregatable_report.h"
 #include "content/browser/aggregation_service/aggregation_service_key_storage.h"
@@ -76,7 +77,7 @@
 
 // Returns empty vector in the case of an error.
 std::vector<uint8_t> DecryptPayloadWithHpke(
-    const std::vector<uint8_t>& payload,
+    base::span<const uint8_t> payload,
     const EVP_HPKE_KEY& key,
     const std::string& expected_serialized_shared_info);
 
diff --git a/content/browser/file_system_access/file_system_access.proto b/content/browser/file_system_access/file_system_access.proto
index fceead4..a54ddbb 100644
--- a/content/browser/file_system_access/file_system_access.proto
+++ b/content/browser/file_system_access/file_system_access.proto
@@ -44,6 +44,9 @@
   // The path to the file or directory relative to the root of the origin's
   // sandboxed file system.
   required bytes virtual_path = 1;
+  // The storage bucket ID. Will be populated only if the non-default bucket
+  // is being used.
+  optional int64 bucket_id = 2;
 }
 
 // Used to serialize any File System Access handle, for example when a handle is
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
index a938af7b..3b60d30 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
@@ -21,9 +21,13 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/bind_post_task.h"
+#include "base/task/sequenced_task_runner.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
+#include "base/threading/sequenced_task_runner_handle.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/cpp/buckets/bucket_id.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/file_system_access/file_system_access.pb.h"
 #include "content/browser/file_system_access/file_system_access_access_handle_host_impl.h"
 #include "content/browser/file_system_access/file_system_access_data_transfer_token_impl.h"
@@ -55,6 +59,7 @@
 #include "third_party/blink/public/mojom/file_system_access/file_system_access_data_transfer_token.mojom.h"
 #include "third_party/blink/public/mojom/file_system_access/file_system_access_error.mojom.h"
 #include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-forward.h"
+#include "third_party/blink/public/mojom/quota/quota_types.mojom-shared.h"
 #include "ui/shell_dialogs/select_file_dialog.h"
 #include "url/gurl.h"
 #include "url/origin.h"
@@ -793,7 +798,9 @@
   } else if (url.type() == storage::kFileSystemTypeTemporary) {
     base::FilePath virtual_path = url.virtual_path();
     data.mutable_sandboxed()->set_virtual_path(SerializePath(virtual_path));
-
+    if (url.bucket().has_value() && !url.bucket()->is_default) {
+      data.mutable_sandboxed()->set_bucket_id(url.bucket()->id.value());
+    }
   } else {
     NOTREACHED();
   }
@@ -805,6 +812,22 @@
   std::move(callback).Run(result);
 }
 
+void FileSystemAccessManagerImpl::DidGetSandboxedBucketForDeserializeHandle(
+    const FileSystemAccessHandleData& data,
+    mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token,
+    const storage::FileSystemURL& url) {
+  auto permission_grant =
+      base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
+          PermissionStatus::GRANTED, base::FilePath());
+  CreateTransferTokenImpl(
+      url, url.storage_key(),
+      SharedHandleState(permission_grant, permission_grant),
+      data.handle_type() == FileSystemAccessHandleData::kDirectory
+          ? HandleType::kDirectory
+          : HandleType::kFile,
+      std::move(token));
+}
+
 void FileSystemAccessManagerImpl::DeserializeHandle(
     const blink::StorageKey& storage_key,
     const std::vector<uint8_t>& bits,
@@ -825,17 +848,30 @@
           DeserializePath(data.sandboxed().virtual_path());
       storage::FileSystemURL url = context()->CreateCrackedFileSystemURL(
           storage_key, storage::kFileSystemTypeTemporary, virtual_path);
-
-      auto permission_grant =
-          base::MakeRefCounted<FixedFileSystemAccessPermissionGrant>(
-              PermissionStatus::GRANTED, base::FilePath());
-      CreateTransferTokenImpl(
-          url, storage_key,
-          SharedHandleState(permission_grant, permission_grant),
-          data.handle_type() == FileSystemAccessHandleData::kDirectory
-              ? HandleType::kDirectory
-              : HandleType::kFile,
-          std::move(token));
+      if (!data.sandboxed().has_bucket_id()) {
+        // Use the default storage bucket.
+        DidGetSandboxedBucketForDeserializeHandle(data, std::move(token), url);
+      } else {
+        // Apply a custom bucket override.
+        auto bucket_callback = base::BindOnce(
+            [](storage::FileSystemURL url,
+               base::OnceCallback<void(const storage::FileSystemURL&)> callback,
+               storage::QuotaErrorOr<storage::BucketInfo> result) {
+              if (!result.ok()) {
+                // Drop `token`, and directly return.
+                return;
+              }
+              url.SetBucket(result->ToBucketLocator());
+              std::move(callback).Run(url);
+            },
+            url,
+            base::BindOnce(&FileSystemAccessManagerImpl::
+                               DidGetSandboxedBucketForDeserializeHandle,
+                           weak_factory_.GetWeakPtr(), data, std::move(token)));
+        context_->quota_manager_proxy()->GetBucketById(
+            storage::BucketId::FromUnsafeValue(data.sandboxed().bucket_id()),
+            base::SequencedTaskRunnerHandle::Get(), std::move(bucket_callback));
+      }
       break;
     }
     case FileSystemAccessHandleData::kLocal:
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h
index 4e6e23b..71972047 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl.h
+++ b/content/browser/file_system_access/file_system_access_manager_impl.h
@@ -16,8 +16,11 @@
 #include "base/threading/sequence_bound.h"
 #include "base/types/pass_key.h"
 #include "components/download/public/common/quarantine_connection.h"
+#include "components/services/storage/public/cpp/buckets/bucket_info.h"
+#include "components/services/storage/public/cpp/quota_error_or.h"
 #include "components/services/storage/public/mojom/file_system_access_context.mojom.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/file_system_access/file_system_access.pb.h"
 #include "content/browser/file_system_access/file_system_access_write_lock_manager.h"
 #include "content/browser/file_system_access/file_system_chooser.h"
 #include "content/common/content_export.h"
@@ -453,10 +456,14 @@
   void DidResolveForSerializeHandle(
       SerializeHandleCallback callback,
       FileSystemAccessTransferTokenImpl* resolved_token);
+  void DidGetSandboxedBucketForDeserializeHandle(
+      const FileSystemAccessHandleData& data,
+      mojo::PendingReceiver<blink::mojom::FileSystemAccessTransferToken> token,
+      const storage::FileSystemURL& url);
 
-  // FileSystemAccessCapacityAllocationHosts may reserve too much capacity from
-  // the quota system. This function determines the file's actual size and
-  // corrects its capacity usage in the quota system.
+  // FileSystemAccessCapacityAllocationHosts may reserve too much capacity
+  // from the quota system. This function determines the file's actual size
+  // and corrects its capacity usage in the quota system.
   void CleanupAccessHandleCapacityAllocation(const storage::FileSystemURL& url,
                                              int64_t allocated_file_size,
                                              base::OnceClosure callback);
diff --git a/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc b/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc
index d3b2bb78..80f3c829a 100644
--- a/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc
+++ b/content/browser/file_system_access/file_system_access_manager_impl_unittest.cc
@@ -18,6 +18,8 @@
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "components/services/storage/public/cpp/buckets/bucket_id.h"
+#include "components/services/storage/public/cpp/buckets/bucket_locator.h"
 #include "content/browser/file_system_access/file_system_access_data_transfer_token_impl.h"
 #include "content/browser/file_system_access/file_system_access_directory_handle_impl.h"
 #include "content/browser/file_system_access/file_system_access_file_handle_impl.h"
@@ -323,6 +325,19 @@
               blink::mojom::FileSystemAccessStatus::kOk);
   }
 
+  storage::BucketLocator CreateBucketForTesting() {
+    base::test::TestFuture<storage::QuotaErrorOr<storage::BucketInfo>>
+        bucket_future;
+    quota_manager_proxy_->CreateBucketForTesting(
+        kTestStorageKey, "custom_bucket", blink::mojom::StorageType::kTemporary,
+        base::SequencedTaskRunnerHandle::Get(), bucket_future.GetCallback());
+    auto bucket = bucket_future.Take();
+    EXPECT_TRUE(bucket.ok());
+    LOG(INFO) << "Created bucket "
+              << bucket->ToBucketLocator().id.GetUnsafeValue();
+    return bucket->ToBucketLocator();
+  }
+
  protected:
   const GURL kTestURL = GURL("https://example.com/test");
   const blink::StorageKey kTestStorageKey =
@@ -427,6 +442,32 @@
   ASSERT_TRUE(root);
 }
 
+TEST_F(FileSystemAccessManagerImplTest, GetSandboxedFileSystem_BadBucket) {
+  mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle>
+      directory_remote;
+  FileSystemAccessManagerImpl::BindingContext binding_context = {
+      kTestStorageKey, kTestURL, web_contents_->GetMainFrame()->GetGlobalId()};
+  const auto bucket = storage::BucketLocator(
+      storage::BucketId(12), kTestStorageKey,
+      blink::mojom::StorageType::kUnknown, /*is_default=*/false);
+
+  base::test::TestFuture<
+      blink::mojom::FileSystemAccessErrorPtr,
+      mojo::PendingRemote<blink::mojom::FileSystemAccessDirectoryHandle>>
+      handle_future;
+  manager_->GetSandboxedFileSystem(binding_context, bucket,
+                                   handle_future.GetCallback());
+  EXPECT_EQ(blink::mojom::FileSystemAccessStatus::kOk,
+            handle_future.Get<0>()->status);
+
+  mojo::Remote<blink::mojom::FileSystemAccessDirectoryHandle> root(
+      std::move(std::get<1>(handle_future.Take())));
+  // Currently we intentionally return a non-functional file/directory handle
+  // in the case of a bad bucket override, as there is currently no better way
+  // of representing a handle to a bucket that no longer exists.
+  ASSERT_TRUE(root);
+}
+
 TEST_F(FileSystemAccessManagerImplTest, GetSandboxedFileSystem_Permissions) {
   base::test::TestFuture<
       blink::mojom::FileSystemAccessErrorPtr,
@@ -707,7 +748,8 @@
       file_system_context_.get(), test_file_url, 3));
 }
 
-TEST_F(FileSystemAccessManagerImplTest, SerializeHandle_SandboxedFile) {
+TEST_F(FileSystemAccessManagerImplTest,
+       SerializeHandle_SandboxedFile_DefaultBucket) {
   auto test_file_url = file_system_context_->CreateCrackedFileSystemURL(
       kTestStorageKey, storage::kFileSystemTypeTemporary,
       base::FilePath::FromUTF8Unsafe("test/foo/bar"));
@@ -720,6 +762,7 @@
   FileSystemAccessTransferTokenImpl* token =
       SerializeAndDeserializeToken(std::move(token_remote));
   ASSERT_TRUE(token);
+  ASSERT_FALSE(token->url().bucket().has_value());
   EXPECT_EQ(test_file_url, token->url());
   EXPECT_EQ(HandleType::kFile, token->type());
 
@@ -731,7 +774,35 @@
   EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus());
 }
 
-TEST_F(FileSystemAccessManagerImplTest, SerializeHandle_SandboxedDirectory) {
+TEST_F(FileSystemAccessManagerImplTest,
+       SerializeHandle_SandboxedFile_CustomBucket) {
+  auto test_file_url = file_system_context_->CreateCrackedFileSystemURL(
+      kTestStorageKey, storage::kFileSystemTypeTemporary,
+      base::FilePath::FromUTF8Unsafe("test/foo/bar"));
+  test_file_url.SetBucket(CreateBucketForTesting());
+  FileSystemAccessFileHandleImpl file(manager_.get(), kBindingContext,
+                                      test_file_url, {ask_grant_, ask_grant_});
+  mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote;
+  manager_->CreateTransferToken(file,
+                                token_remote.InitWithNewPipeAndPassReceiver());
+
+  FileSystemAccessTransferTokenImpl* token =
+      SerializeAndDeserializeToken(std::move(token_remote));
+  ASSERT_TRUE(token);
+  ASSERT_TRUE(token->url().bucket().has_value());
+  EXPECT_EQ(test_file_url, token->url());
+  EXPECT_EQ(HandleType::kFile, token->type());
+
+  // Deserialized sandboxed filesystem handles should always be readable and
+  // writable.
+  ASSERT_TRUE(token->GetReadGrant());
+  EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus());
+  ASSERT_TRUE(token->GetWriteGrant());
+  EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus());
+}
+
+TEST_F(FileSystemAccessManagerImplTest,
+       SerializeHandle_SandboxedDirectory_DefaultBucket) {
   auto test_file_url = file_system_context_->CreateCrackedFileSystemURL(
       kTestStorageKey, storage::kFileSystemTypeTemporary,
       base::FilePath::FromUTF8Unsafe("hello/world/"));
@@ -744,6 +815,34 @@
   FileSystemAccessTransferTokenImpl* token =
       SerializeAndDeserializeToken(std::move(token_remote));
   ASSERT_TRUE(token);
+  ASSERT_FALSE(token->url().bucket().has_value());
+  EXPECT_EQ(test_file_url, token->url());
+  EXPECT_EQ(HandleType::kDirectory, token->type());
+
+  // Deserialized sandboxed filesystem handles should always be readable and
+  // writable.
+  ASSERT_TRUE(token->GetReadGrant());
+  EXPECT_EQ(PermissionStatus::GRANTED, token->GetReadGrant()->GetStatus());
+  ASSERT_TRUE(token->GetWriteGrant());
+  EXPECT_EQ(PermissionStatus::GRANTED, token->GetWriteGrant()->GetStatus());
+}
+
+TEST_F(FileSystemAccessManagerImplTest,
+       SerializeHandle_SandboxedDirectory_CustomBucket) {
+  auto test_file_url = file_system_context_->CreateCrackedFileSystemURL(
+      kTestStorageKey, storage::kFileSystemTypeTemporary,
+      base::FilePath::FromUTF8Unsafe("hello/world/"));
+  test_file_url.SetBucket(CreateBucketForTesting());
+  FileSystemAccessDirectoryHandleImpl directory(
+      manager_.get(), kBindingContext, test_file_url, {ask_grant_, ask_grant_});
+  mojo::PendingRemote<blink::mojom::FileSystemAccessTransferToken> token_remote;
+  manager_->CreateTransferToken(directory,
+                                token_remote.InitWithNewPipeAndPassReceiver());
+
+  FileSystemAccessTransferTokenImpl* token =
+      SerializeAndDeserializeToken(std::move(token_remote));
+  ASSERT_TRUE(token);
+  ASSERT_TRUE(token->url().bucket().has_value());
   EXPECT_EQ(test_file_url, token->url());
   EXPECT_EQ(HandleType::kDirectory, token->type());
 
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.cc b/content/browser/gpu/browser_gpu_channel_host_factory.cc
index de397aaf..96895bf 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -38,7 +38,6 @@
 #include "gpu/config/gpu_finch_features.h"
 #include "gpu/ipc/common/gpu_client_ids.h"
 #include "gpu/ipc/common/gpu_watchdog_timeout.h"
-#include "gpu/ipc/in_process_command_buffer.h"
 #include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
 
 #if BUILDFLAG(IS_MAC)
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 8ca8002..954aa49 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -66,7 +66,6 @@
 #include "gpu/ipc/common/gpu_client_ids.h"
 #include "gpu/ipc/common/result_codes.h"
 #include "gpu/ipc/host/shader_disk_cache.h"
-#include "gpu/ipc/in_process_command_buffer.h"
 #include "media/base/media_switches.h"
 #include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller.h b/content/browser/renderer_host/input/synthetic_gesture_controller.h
index a9f9de8..f4c1479 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller.h
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -155,7 +155,7 @@
   // truly robust. https://crbug.com/985374.
   bool renderer_known_to_be_initialized_ = false;
 
-  base::RepeatingTimer dispatch_timer_;
+  base::MetronomeTimer dispatch_timer_;
   base::WeakPtrFactory<SyntheticGestureController> weak_ptr_factory_{this};
 };
 
diff --git a/content/test/data/media/canplaytype_test.js b/content/test/data/media/canplaytype_test.js
index 14224e8..21ab9f3 100644
--- a/content/test/data/media/canplaytype_test.js
+++ b/content/test/data/media/canplaytype_test.js
@@ -1263,6 +1263,27 @@
   if (!testMimeCodec('video/mp4; codecs="avc1.42E052"', P_MAYBE))
     return false;
 
+  // Levels 6 (0x3C), 6.1 (0x3D), 6.2 (0x3E).
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E03B"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E03C"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E03D"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E03E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E03F"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E006"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E060"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E061"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E062"', P_MAYBE))
+    return false;
+
   return true;
 }
 
diff --git a/device/bluetooth/dbus/bluetooth_device_client.cc b/device/bluetooth/dbus/bluetooth_device_client.cc
index ed4cec2..a133049 100644
--- a/device/bluetooth/dbus/bluetooth_device_client.cc
+++ b/device/bluetooth/dbus/bluetooth_device_client.cc
@@ -28,9 +28,11 @@
 
 namespace {
 
+#if BUILDFLAG(IS_CHROMEOS_ASH)
 // TODO(b/213229904): Remove this constant and replace with
 // |bluetooth_device::kDisconnectOld| once it has been uprev'd.
 constexpr char kDisconnectOldPlaceholder[] = "DisconnectOld";
+#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Value returned for the the RSSI or TX power if it cannot be read.
 const int kUnknownPower = 127;
@@ -377,7 +379,7 @@
                                   ? bluetooth_device::kDisconnect
                                   : kDisconnectOldPlaceholder;
 #else   // BUILDFLAG(IS_CHROMEOS_ASH)
-    const char* method_name = kDisconnectOldPlaceholder;
+    const char* method_name = bluetooth_device::kDisconnect;
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
     dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
                                  method_name);
diff --git a/extensions/browser/extension_frame_host_browsertest.cc b/extensions/browser/extension_frame_host_browsertest.cc
index 2378420..bdd70af 100644
--- a/extensions/browser/extension_frame_host_browsertest.cc
+++ b/extensions/browser/extension_frame_host_browsertest.cc
@@ -162,7 +162,8 @@
     ExtensionWebContentsObserver* observer =
         extensions_browser_client_->GetExtensionWebContentsObserver(
             host->host_contents());
-    static_cast<TestExtensionFrameHost*>(observer->extension_frame_host_.get())
+    static_cast<TestExtensionFrameHost*>(
+        observer->extension_frame_host_for_testing())
         ->SetInvalidRequest(method_name);
   }
 
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 8c9128e..c4ca2a3 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -1622,7 +1622,7 @@
   WMDESKSPRIVATE_UPDATEDESKTEMPLATE = 1559,
   WMDESKSPRIVATE_GETSAVEDDESKTEMPLATES = 1560,
   WMDESKSPRIVATE_DELETEDESKTEMPLATE = 1561,
-  WMDESKSPRIVATE_LAUNCHDESKTEMPLATE = 1562,
+  WMDESKSPRIVATE_LAUNCHDESK = 1562,
   AUTOTESTPRIVATE_SETSHELFICONPIN = 1563,
   SCRIPTING_GETREGISTEREDCONTENTSCRIPTS = 1564,
   OS_TELEMETRY_GETVPDINFO = 1565,
@@ -1719,7 +1719,7 @@
   ACCESSIBILITY_PRIVATE_INSTALLPUMPKINFORDICTATION = 1656,
   BOOKMARKMANAGERPRIVATE_OPENINNEWTAB = 1657,
   BOOKMARKMANAGERPRIVATE_OPENINNEWWINDOW = 1658,
-  WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS = 1659,
+  WMDESKSPRIVATE_REMOVEDESK = 1659,
   SHAREDSTORAGEPRIVATE_GET = 1660,
   SHAREDSTORAGEPRIVATE_SET = 1661,
   SHAREDSTORAGEPRIVATE_REMOVE = 1662,
diff --git a/extensions/browser/extension_web_contents_observer.h b/extensions/browser/extension_web_contents_observer.h
index 7beed9b2..16ce6db 100644
--- a/extensions/browser/extension_web_contents_observer.h
+++ b/extensions/browser/extension_web_contents_observer.h
@@ -101,6 +101,10 @@
   // ExtensionWebContentsObserver has already been initialized.
   void ListenToWindowIdChangesFrom(sessions::SessionTabHelper* helper);
 
+  ExtensionFrameHost* extension_frame_host_for_testing() {
+    return extension_frame_host_.get();
+  }
+
  protected:
   explicit ExtensionWebContentsObserver(content::WebContents* web_contents);
   ~ExtensionWebContentsObserver() override;
@@ -144,8 +148,6 @@
  private:
   using PassKey = base::PassKey<ExtensionWebContentsObserver>;
 
-  friend class ExtensionFrameHostBrowserTest;
-
   void OnWindowIdChanged(const SessionID& id);
 
   // The BrowserContext associated with the WebContents being observed.
diff --git a/gpu/ipc/BUILD.gn b/gpu/ipc/BUILD.gn
index c418f42..6948ed2a 100644
--- a/gpu/ipc/BUILD.gn
+++ b/gpu/ipc/BUILD.gn
@@ -31,12 +31,6 @@
   deps = [
     "//base",
     "//base/third_party/dynamic_annotations",
-
-    # crbug.com/799267: crash_key needs to be added explicitly for Windows and
-    # Mac even though it's not directly referenced, because it's being
-    # implicitly depended upon by gpu/config/gpu_crash_keys.h but deps (even
-    # public ones) are not transitive for static libraries.
-    "//components/crash/core/common:crash_key",
     "//gpu/command_buffer/client",
     "//gpu/command_buffer/client:gles2_cmd_helper",
     "//gpu/command_buffer/client:gles2_implementation",
diff --git a/infra/config/generated/builders/try/win7-blink-rel/properties.json b/infra/config/generated/builders/try/win7-blink-rel/properties.json
deleted file mode 100644
index be0cfff..0000000
--- a/infra/config/generated/builders/try/win7-blink-rel/properties.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
-  "$build/goma": {
-    "enable_ats": false,
-    "rpc_extra_params": "?prod",
-    "server_host": "goma.chromium.org",
-    "use_luci_auth": true
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "tryserver.blink",
-  "recipe": "chromium_trybot"
-}
\ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 5682bd2..3439600d 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -1926,10 +1926,6 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/win7-blink-rel"
-        includable_only: true
-      }
-      builders {
         name: "chromium/try/win7-rel"
         location_regexp: ".+/[+]/sandbox/win/.+"
         location_regexp: ".+/[+]/sandbox/policy/win/.+"
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 95ec790..7bb415f 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -75429,96 +75429,6 @@
       }
     }
     builders {
-      name: "win7-blink-rel"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builderless:1"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Windows"
-      dimensions: "pool:luci.chromium.try"
-      dimensions: "ssd:0"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/try/win7-blink-rel/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "tryserver.blink",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium_trybot"'
-        '}'
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      grace_period {
-        seconds: 120
-      }
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
-            }
-          }
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "blink_web_tests_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://[^/]*blink_web_tests/.+"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-    }
-    builders {
       name: "win7-rel"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builderless:1"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index ea14bc3..32a87ca1 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -16405,9 +16405,6 @@
     name: "buildbucket/luci.chromium.try/win32-official"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/win7-blink-rel"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/win7-rel"
   }
   builders {
@@ -16479,9 +16476,6 @@
   builders {
     name: "buildbucket/luci.chromium.try/win11-blink-rel"
   }
-  builders {
-    name: "buildbucket/luci.chromium.try/win7-blink-rel"
-  }
   builder_view_only: true
 }
 consoles {
diff --git a/infra/config/subprojects/chromium/try/tryserver.blink.star b/infra/config/subprojects/chromium/try/tryserver.blink.star
index 738beb9..987870b 100644
--- a/infra/config/subprojects/chromium/try/tryserver.blink.star
+++ b/infra/config/subprojects/chromium/try/tryserver.blink.star
@@ -86,13 +86,6 @@
     builderless = True,
 )
 
-try_.builder(
-    name = "win7-blink-rel",
-    goma_backend = goma.backend.RBE_PROD,
-    os = os.WINDOWS_ANY,
-    builderless = True,
-)
-
 blink_mac_builder(
     name = "mac10.13-blink-rel",
 )
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index e90cb694..5877623 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -942,6 +942,10 @@
      flag_descriptions::kDefaultBrowserIntentsShowSettingsName,
      flag_descriptions::kDefaultBrowserIntentsShowSettingsDescription,
      flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDefaultBrowserIntentsShowSettings)},
+    {"enable-discover-feed-ghost-cards",
+     flag_descriptions::kEnableDiscoverFeedGhostCardsName,
+     flag_descriptions::kEnableDiscoverFeedGhostCardsDescription,
+     flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDiscoverFeedGhostCardsEnabled)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 97622a325..68223d4 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -225,6 +225,11 @@
 const char kEnableDiscoverFeedPreviewDescription[] =
     "Enable showing a live preview for discover feed long-press menu.";
 
+const char kEnableDiscoverFeedGhostCardsName[] =
+    "Enable discover feed ghost cards";
+const char kEnableDiscoverFeedGhostCardsDescription[] =
+    "Show ghost cards when refreshing the discover feed.";
+
 const char kEnableDiscoverFeedShorterCacheName[] =
     "Enable discover feed shorter cache";
 const char kEnableDiscoverFeedShorterCacheDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index def07b45..0d4204fe 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -209,6 +209,11 @@
 extern const char kEnableDiscoverFeedPreviewName[];
 extern const char kEnableDiscoverFeedPreviewDescription[];
 
+// Title and description for the flag to show ghost cards when refreshing the
+// discover feed.
+extern const char kEnableDiscoverFeedGhostCardsName[];
+extern const char kEnableDiscoverFeedGhostCardsDescription[];
+
 // Title and description for the flag to shorten the cache.
 extern const char kEnableDiscoverFeedShorterCacheName[];
 extern const char kEnableDiscoverFeedShorterCacheDescription[];
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
index 6677d2a..abb1caa 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.h
@@ -30,6 +30,7 @@
   // TabRestoreServiceClient:
   sessions::LiveTabContext* CreateLiveTabContext(
       sessions::LiveTabContext* existing_context,
+      sessions::SessionWindow::WindowType type,
       const std::string& app_name,
       const gfx::Rect& bounds,
       ui::WindowShowState show_state,
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
index c751263..cc36cf0 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -62,6 +62,7 @@
 sessions::LiveTabContext*
 IOSChromeTabRestoreServiceClient::CreateLiveTabContext(
     sessions::LiveTabContext* /* existing_context */,
+    sessions::SessionWindow::WindowType type,
     const std::string& /* app_name */,
     const gfx::Rect& /* bounds */,
     ui::WindowShowState /* show_state */,
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
index 4df9b3e..e7bd7bf 100644
--- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
+++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.h
@@ -31,6 +31,7 @@
   // Sessions::LiveTabContext:
   void ShowBrowserWindow() override;
   SessionID GetSessionID() const override;
+  sessions::SessionWindow::WindowType GetWindowType() const override;
   int GetTabCount() const override;
   int GetSelectedIndex() const override;
   std::string GetAppName() const override;
diff --git a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
index f85dec4..654d3bc 100644
--- a/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
+++ b/ios/chrome/browser/sessions/live_tab_context_browser_agent.mm
@@ -41,6 +41,12 @@
   return session_id_;
 }
 
+sessions::SessionWindow::WindowType LiveTabContextBrowserAgent::GetWindowType()
+    const {
+  // Not supported by iOS.
+  return sessions::SessionWindow::TYPE_NORMAL;
+}
+
 int LiveTabContextBrowserAgent::GetTabCount() const {
   return web_state_list_->count();
 }
diff --git a/ios/chrome/browser/ui/activity_services/BUILD.gn b/ios/chrome/browser/ui/activity_services/BUILD.gn
index bddbd163..9980d20 100644
--- a/ios/chrome/browser/ui/activity_services/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/BUILD.gn
@@ -44,6 +44,7 @@
     "//ios/chrome/browser/ui/util:url_with_title",
     "//ios/chrome/browser/web",
     "//ios/chrome/browser/web_state_list",
+    "//ios/web/public/js_messaging",
     "//ui/base",
     "//url",
   ]
diff --git a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h
index 6a6ff80..01d66a0f 100644
--- a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h
+++ b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.h
@@ -15,6 +15,10 @@
 
 namespace activity_services {
 
+// Script to access the canonical URL from a web page. This script shouldn't be
+// used directly, but is exposed for testing purposes.
+extern const char16_t kCanonicalURLScript[];
+
 // Retrieves the canonical URL in the web page represented by `web_state`.
 // This method is asynchronous and the URL is returned by calling the
 // `completion` block.
diff --git a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm
index 2d67b61..c5b7183e 100644
--- a/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm
+++ b/ios/chrome/browser/ui/activity_services/canonical_url_retriever.mm
@@ -10,6 +10,8 @@
 #include "base/values.h"
 #include "components/ui_metrics/canonical_url_share_metrics_types.h"
 #import "ios/chrome/browser/procedural_block_types.h"
+#include "ios/web/public/js_messaging/web_frame.h"
+#import "ios/web/public/js_messaging/web_frame_util.h"
 #import "ios/web/public/web_state.h"
 #include "url/gurl.h"
 
@@ -18,12 +20,6 @@
 #endif
 
 namespace {
-// Script to access the canonical URL from a web page.
-const char16_t kCanonicalURLScript[] =
-    u"(function() {"
-    u"  var linkNode = document.querySelector(\"link[rel='canonical']\");"
-    u"  return linkNode ? linkNode.getAttribute(\"href\") : \"\";"
-    u"})()";
 
 // Logs `result` in the Mobile.CanonicalURLResult histogram.
 void LogCanonicalUrlResultHistogram(ui_metrics::CanonicalURLResult result) {
@@ -62,6 +58,13 @@
 }  // namespace
 
 namespace activity_services {
+
+const char16_t kCanonicalURLScript[] =
+    u"(function() {"
+    u"  var linkNode = document.querySelector(\"link[rel='canonical']\");"
+    u"  return linkNode ? linkNode.getAttribute(\"href\") : \"\";"
+    u"})()";
+
 void RetrieveCanonicalUrl(web::WebState* web_state,
                           ProceduralBlockWithURL completion) {
   // Do not use the canonical URL if the page is not secured with HTTPS.
@@ -72,6 +75,12 @@
     return;
   }
 
+  web::WebFrame* main_frame = web::GetMainFrame(web_state);
+  if (!main_frame) {
+    completion(GURL::EmptyGURL());
+    return;
+  }
+
   void (^javascript_completion)(const base::Value*) =
       ^(const base::Value* value) {
         GURL canonical_url = UrlFromValue(value);
@@ -94,7 +103,7 @@
         completion(canonical_url);
       };
 
-  web_state->ExecuteJavaScript(kCanonicalURLScript,
-                               base::BindOnce(javascript_completion));
+  main_frame->ExecuteJavaScript(kCanonicalURLScript,
+                                base::BindOnce(javascript_completion));
 }
 }  // namespace activity_services
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h
index 8bc0c6ce..accff4a 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.h
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.h
@@ -11,6 +11,9 @@
 // the feed context menu.
 extern const base::Feature kEnableDiscoverFeedPreview;
 
+// Feature flag to show ghost cards when refreshing the discover feed.
+extern const base::Feature kDiscoverFeedGhostCardsEnabled;
+
 // Feature flag to enable shorter cache so that more ghost cards appear.
 extern const base::Feature kEnableDiscoverFeedShorterCache;
 
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm
index c83976eb..d52ac642 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_feature.mm
@@ -16,6 +16,9 @@
 const base::Feature kEnableDiscoverFeedAppFlows{
     "EnableDiscoverFeedAppFlows", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kDiscoverFeedGhostCardsEnabled{
+    "DiscoverFeedGhostCardsEnabled", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kEnableDiscoverFeedShorterCache{
     "EnableDiscoverFeedShorterCache", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -44,9 +47,6 @@
 const base::Feature kEnableFeedAblation{"FeedAblationEnabled",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kDiscoverFeedGhostCardsEnabled{
-    "DiscoverFeedGhostCardsEnabled", base::FEATURE_DISABLED_BY_DEFAULT};
-
 bool IsDiscoverFeedPreviewEnabled() {
   return base::FeatureList::IsEnabled(kEnableDiscoverFeedPreview);
 }
@@ -55,6 +55,10 @@
   return base::FeatureList::IsEnabled(kEnableDiscoverFeedAppFlows);
 }
 
+bool IsDiscoverFeedGhostCardsEnabled() {
+  return base::FeatureList::IsEnabled(kDiscoverFeedGhostCardsEnabled);
+}
+
 bool IsDiscoverFeedShorterCacheEnabled() {
   return base::FeatureList::IsEnabled(kEnableDiscoverFeedShorterCache);
 }
@@ -70,7 +74,3 @@
 bool IsFeedAblationEnabled() {
   return base::FeatureList::IsEnabled(kEnableFeedAblation);
 }
-
-bool IsDiscoverFeedGhostCardsEnabled() {
-  return base::FeatureList::IsEnabled(kDiscoverFeedGhostCardsEnabled);
-}
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
index 98613c57..2694540 100644
--- a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
@@ -9,6 +9,7 @@
 
 #import "base/ios/block_types.h"
 #import "base/strings/sys_string_conversions.h"
+#import "base/test/ios/wait_util.h"
 #import "base/values.h"
 #import "components/bookmarks/browser/bookmark_model.h"
 #import "components/bookmarks/browser/bookmark_node.h"
@@ -17,6 +18,7 @@
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/browser/ui/activity_services/activity_params.h"
+#import "ios/chrome/browser/ui/activity_services/canonical_url_retriever.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_presentation.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.h"
@@ -34,6 +36,8 @@
 #import "ios/chrome/browser/web_state_list/web_state_opener.h"
 #import "ios/chrome/test/scoped_key_window.h"
 #import "ios/web/public/test/fakes/fake_navigation_manager.h"
+#import "ios/web/public/test/fakes/fake_web_frame.h"
+#import "ios/web/public/test/fakes/fake_web_frames_manager.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "ios/web/public/test/web_task_environment.h"
 #import "ios/web/public/web_state.h"
@@ -49,23 +53,11 @@
 #error "This file requires ARC support."
 #endif
 
+using base::test::ios::kWaitForActionTimeout;
+using base::test::ios::WaitUntilConditionOrTimeout;
 using bookmarks::BookmarkModel;
 using bookmarks::BookmarkNode;
 
-namespace {
-
-class MockWebState : public web::FakeWebState {
- public:
-  MockWebState() : web::FakeWebState() {
-    SetNavigationManager(std::make_unique<web::FakeNavigationManager>());
-  }
-
-  MOCK_METHOD2(ExecuteJavaScript,
-               void(const std::u16string&, JavaScriptResultCallback));
-};
-
-}  // namespace
-
 // Test fixture for testing SharingCoordinator.
 class SharingCoordinatorTest : public BookmarkIOSUnitTest {
  protected:
@@ -112,16 +104,22 @@
   // Create a test web state.
   GURL test_url = GURL("https://example.com");
   base::Value url_value = base::Value(test_url.spec());
-  auto test_web_state = std::make_unique<MockWebState>();
+  auto test_web_state = std::make_unique<web::FakeWebState>();
+  test_web_state->SetNavigationManager(
+      std::make_unique<web::FakeNavigationManager>());
   test_web_state->SetCurrentURL(test_url);
   test_web_state->SetBrowserState(browser_->GetBrowserState());
 
-  EXPECT_CALL(*test_web_state, ExecuteJavaScript(testing::_, testing::_))
-      .WillOnce(testing::Invoke(
-          [&](const std::u16string& javascript,
-              base::OnceCallback<void(const base::Value*)> callback) {
-            std::move(callback).Run(&url_value);
-          }));
+  auto frames_manager = std::make_unique<web::FakeWebFramesManager>();
+  web::FakeWebFramesManager* frames_manager_ptr = frames_manager.get();
+  test_web_state->SetWebFramesManager(std::move(frames_manager));
+
+  auto main_frame = web::FakeWebFrame::CreateMainWebFrame(test_url);
+  web::FakeWebFrame* main_frame_ptr = main_frame.get();
+  frames_manager_ptr->AddWebFrame(std::move(main_frame));
+
+  main_frame_ptr->AddResultForExecutedJs(
+      &url_value, activity_services::kCanonicalURLScript);
 
   AppendNewWebState(std::move(test_web_state));
 
@@ -134,11 +132,13 @@
                           params:params
                       originView:fake_origin_view_];
 
+  __block bool completion_handler_called = false;
   id vc_partial_mock = OCMPartialMock(base_view_controller_);
   [[vc_partial_mock expect]
       presentViewController:[OCMArg checkWithBlock:^BOOL(
                                         UIViewController* viewController) {
         if ([viewController isKindOfClass:[UIActivityViewController class]]) {
+          completion_handler_called = true;
           return YES;
         }
         return NO;
@@ -148,6 +148,11 @@
 
   [coordinator start];
 
+  EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForActionTimeout, ^bool {
+    base::RunLoop().RunUntilIdle();
+    return completion_handler_called;
+  }));
+
   // Verify that the positioning is correct.
   auto activityHandler =
       static_cast<id<ActivityServicePositioner, ActivityServicePresentation>>(
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 37c8bdc..0cefa12 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-9a117bef0efc4128cfb05e3566ecf34d46007f5a
\ No newline at end of file
+6bf982611d5c4df13a2a694e07b182da931b7609
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 76c11a3..6b986d0 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-fb4f4d655a9af0e5f535880df2b870ca606135a5
\ No newline at end of file
+0a2ee68f386929280534369f3858b2ec6497d6e4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 7c6b2fe..a911838 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-a8f1f7cb363771d05030693363b73933abbba92c
\ No newline at end of file
+f597692672207e9c5fbc1f0435591aca9471a21d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 866c5a8..02f99a7 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-72b79f580d22e73ecb7e2d2f16d748faa7b2cb21
\ No newline at end of file
+383e79d3130539196d27a4fbccec41dd7f6ab488
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
index 0316cf1..d400f68 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-18a78ea8199b44e099777cc994bc7acc9760e62b
\ No newline at end of file
+35e93d58bb31865b013d3f32a6b3e8aaa9321cf5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
index 2ad1973..7e7bc63c 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-80cc21c2c57a8b0831a196d56120d42227b47cd7
\ No newline at end of file
+b4e9292d84fc93cb2a16a05cb6f04b53a5d145cc
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 604be80c..657c385 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-f478a85c3680bdf12332e7ec730ec9fd02834790
\ No newline at end of file
+06408c87551305288ac232f7bf2576926f78eabc
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index e159fcc..d4304aa 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-bd14906db5ced5528879650bb682ca1d9f438b0c
\ No newline at end of file
+e7fe7e2eb02066dc5c52bdee3dd2190fc0e21c69
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 46f828b..983c18b 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e8832202c32bb95a748f359947dd32cbc7f9476f
\ No newline at end of file
+346f2fa38431c6da6d0a2280443f260df8f9810a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 332151d..2d2a5d88 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-329293142b22e0528d2ea84e579e6ff8ad9bbff8
\ No newline at end of file
+0ee06675c5b8b389b607774ef0f62431b3e7c389
\ No newline at end of file
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index 57cf724..43a6e646 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -73,6 +73,7 @@
   "src/components/BottomNavigation/src/MaterialBottomNavigation+BottomNavigationController.h",
   "src/components/BottomNavigation/src/MaterialBottomNavigation.h",
   "src/components/BottomNavigation/src/PerformantShadowMigration/MDCBottomNavigationBar+ShadowsPrivate.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.h",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.h",
@@ -300,6 +301,7 @@
   "src/components/Ripple/src/private/MDCRippleLayerDelegate.h",
   "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.h",
   "src/components/ScalableFontDescriptor/src/MaterialScalableFontDescriptor.h",
+  "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h",
   "src/components/Shadow/src/MDCShadow.h",
   "src/components/Shadow/src/MDCShadowsCollection.h",
   "src/components/Shadow/src/MaterialShadow.h",
@@ -650,6 +652,7 @@
   "src/components/Ripple/src/private",
   "src/components/ScalableFontDescriptor/src",
   "src/components/Shadow/src",
+  "src/components/Shadow/src/Animations",
   "src/components/ShadowElevations/src",
   "src/components/ShadowLayer/src",
   "src/components/ShapeLibrary/src",
@@ -817,6 +820,8 @@
   "src/components/BottomNavigation/src/MaterialBottomNavigation+BottomNavigationController.h",
   "src/components/BottomNavigation/src/MaterialBottomNavigation.h",
   "src/components/BottomNavigation/src/PerformantShadowMigration/MDCBottomNavigationBar+ShadowsPrivate.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+ItemView.m",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h",
   "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.m",
@@ -1162,6 +1167,8 @@
   "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.h",
   "src/components/ScalableFontDescriptor/src/MDCScalableFontDescriptor.m",
   "src/components/ScalableFontDescriptor/src/MaterialScalableFontDescriptor.h",
+  "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.h",
+  "src/components/Shadow/src/Animations/UIView+MDCShadowAnimations.m",
   "src/components/Shadow/src/MDCShadow.h",
   "src/components/Shadow/src/MDCShadow.m",
   "src/components/Shadow/src/MDCShadowsCollection.h",
diff --git a/ios/web/public/test/fakes/fake_web_frame.h b/ios/web/public/test/fakes/fake_web_frame.h
index afd7f82..1152700 100644
--- a/ios/web/public/test/fakes/fake_web_frame.h
+++ b/ios/web/public/test/fakes/fake_web_frame.h
@@ -57,6 +57,13 @@
   virtual void AddJsResultForFunctionCall(base::Value* js_result,
                                           const std::string& function_name) = 0;
 
+  // Sets |js_result| that will be passed into callback for |executed_js|
+  // call through ExecuteJavaScript API.
+  // NOTE: The caller is responsible for keeping |js_result| alive for as
+  // long as this instance lives.
+  virtual void AddResultForExecutedJs(base::Value* js_result,
+                                      const std::u16string& executed_js) = 0;
+
   virtual void set_force_timeout(bool force_timeout) = 0;
 
   // Sets return value |can_call_function_| of CanCallJavaScriptFunction(),
diff --git a/ios/web/test/fakes/fake_web_frame_impl.cc b/ios/web/test/fakes/fake_web_frame_impl.cc
index 566c01ca..10a69602 100644
--- a/ios/web/test/fakes/fake_web_frame_impl.cc
+++ b/ios/web/test/fakes/fake_web_frame_impl.cc
@@ -155,14 +155,31 @@
     const std::u16string& script,
     base::OnceCallback<void(const base::Value*)> callback) {
   java_script_calls_.push_back(script);
-  return false;
+
+  const base::Value* result = executed_js_result_map_[script];
+
+  if (!callback.is_null()) {
+    GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), result));
+  }
+
+  return result != nullptr;
 }
 
 bool FakeWebFrameImpl::ExecuteJavaScript(
     const std::u16string& script,
     base::OnceCallback<void(const base::Value*, bool)> callback) {
   java_script_calls_.push_back(script);
-  return false;
+
+  const base::Value* result = executed_js_result_map_[script];
+  bool success = result != nullptr;
+
+  if (!callback.is_null()) {
+    GetUIThreadTaskRunner({})->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), result, success));
+  }
+
+  return success;
 }
 
 void FakeWebFrameImpl::AddJsResultForFunctionCall(
@@ -171,6 +188,12 @@
   result_map_[function_name] = js_result;
 }
 
+void FakeWebFrameImpl::AddResultForExecutedJs(
+    base::Value* js_result,
+    const std::u16string& executed_js) {
+  executed_js_result_map_[executed_js] = js_result;
+}
+
 JavaScriptContentWorld* FakeWebFrameImpl::last_received_content_world() {
   return last_received_content_world_;
 }
diff --git a/ios/web/test/fakes/fake_web_frame_impl.h b/ios/web/test/fakes/fake_web_frame_impl.h
index 556a98b..d081ce5 100644
--- a/ios/web/test/fakes/fake_web_frame_impl.h
+++ b/ios/web/test/fakes/fake_web_frame_impl.h
@@ -56,6 +56,8 @@
   void set_browser_state(BrowserState* browser_state) override;
   void AddJsResultForFunctionCall(base::Value* js_result,
                                   const std::string& function_name) override;
+  void AddResultForExecutedJs(base::Value* js_result,
+                              const std::u16string& executed_js) override;
   void set_force_timeout(bool force_timeout) override;
   void set_can_call_function(bool can_call_function) override;
   void set_call_java_script_function_callback(
@@ -90,6 +92,9 @@
   // by JavaScript function |name| expected to be passed into
   // CallJavaScriptFunction().
   std::map<std::string, base::Value*> result_map_;
+  // Map holding values to be passed in ExecuteJavaScript() callback. Keyed by
+  // by JavaScript expected to be passed to ExecuteJavaScript().
+  std::map<std::u16string, base::Value*> executed_js_result_map_;
   // The frame identifier which uniquely identifies this frame across the
   // application's lifetime.
   std::string frame_id_;
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 5aaa7a1..0ba71149 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -130,7 +130,8 @@
           (level_idc >= 20 && level_idc <= 22) ||
           (level_idc >= 30 && level_idc <= 32) ||
           (level_idc >= 40 && level_idc <= 42) ||
-          (level_idc >= 50 && level_idc <= 52));
+          (level_idc >= 50 && level_idc <= 52) ||
+          (level_idc >= 60 && level_idc <= 62));
 }
 
 // Make a default ParsedCodecResult. Values should indicate "unspecified"
diff --git a/media/base/video_util.cc b/media/base/video_util.cc
index 60475b69d..56a4a9a6 100644
--- a/media/base/video_util.cc
+++ b/media/base/video_util.cc
@@ -775,18 +775,19 @@
   if (!src_frame.IsMappable() || !dst_frame.IsMappable())
     return EncoderStatus::Codes::kUnsupportedFrameFormat;
 
-  // I420A can only be produced from I420A.
-  if (dst_frame.format() == PIXEL_FORMAT_I420A &&
-      src_frame.format() != PIXEL_FORMAT_I420A) {
-    return EncoderStatus::Codes::kUnsupportedFrameFormat;
-  }
-
-  if ((dst_frame.format() == PIXEL_FORMAT_I420 ||
+  if ((dst_frame.format() == PIXEL_FORMAT_I420A ||
+       dst_frame.format() == PIXEL_FORMAT_I420 ||
        dst_frame.format() == PIXEL_FORMAT_NV12) &&
       (src_frame.format() == PIXEL_FORMAT_XBGR ||
        src_frame.format() == PIXEL_FORMAT_XRGB ||
        src_frame.format() == PIXEL_FORMAT_ABGR ||
        src_frame.format() == PIXEL_FORMAT_ARGB)) {
+    if (!media::IsOpaque(dst_frame.format()) &&
+        media::IsOpaque(src_frame.format())) {
+      // We can drop an alpha channel, but we don't add it out of nothing.
+      return EncoderStatus::Codes::kUnsupportedFrameFormat;
+    }
+
     // libyuv's RGB to YUV methods always output BT.601.
     dst_frame.set_color_space(gfx::ColorSpace::CreateREC601());
 
@@ -812,7 +813,8 @@
       src_stride = stride;
     }
 
-    if (dst_frame.format() == PIXEL_FORMAT_I420) {
+    if (dst_frame.format() == PIXEL_FORMAT_I420 ||
+        dst_frame.format() == PIXEL_FORMAT_I420A) {
       auto convert_fn = (src_frame.format() == PIXEL_FORMAT_XBGR ||
                          src_frame.format() == PIXEL_FORMAT_ABGR)
                             ? libyuv::ABGRToI420
@@ -827,6 +829,17 @@
           dst_frame.visible_rect().width(), dst_frame.visible_rect().height());
       if (error)
         return EncoderStatus::Codes::kFormatConversionError;
+
+      if (dst_frame.format() == PIXEL_FORMAT_I420A) {
+        // Convert alpha channel separately
+        libyuv::ARGBExtractAlpha(
+            src_data, src_stride,
+            dst_frame.visible_data(media::VideoFrame::kAPlane),
+            dst_frame.stride(media::VideoFrame::kAPlane),
+            dst_frame.visible_rect().width(),
+            dst_frame.visible_rect().height());
+      }
+
       return OkStatus();
     }
 
diff --git a/media/gpu/chromeos/video_decoder_pipeline.cc b/media/gpu/chromeos/video_decoder_pipeline.cc
index 4938dcf..79263cd0 100644
--- a/media/gpu/chromeos/video_decoder_pipeline.cc
+++ b/media/gpu/chromeos/video_decoder_pipeline.cc
@@ -678,9 +678,9 @@
 #error "Unsupported platform"
 #endif
 
-#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
+#if BUILDFLAG(IS_LINUX)
   // viable_candidate should always be set unless using L1 protected content,
-  // which isn't an option on linux or lacros.
+  // which isn't an option on linux.
   CHECK(viable_candidate);
 #endif
 
diff --git a/media/gpu/v4l2/BUILD.gn b/media/gpu/v4l2/BUILD.gn
index 50d81e48..6a635eff 100644
--- a/media/gpu/v4l2/BUILD.gn
+++ b/media/gpu/v4l2/BUILD.gn
@@ -160,6 +160,7 @@
   sources = [
     "test/av1_decoder.cc",
     "test/av1_decoder.h",
+    "test/av1_pix_fmt.h",
     "test/v4l2_ioctl_shim.cc",
     "test/v4l2_ioctl_shim.h",
     "test/v4l2_stateless_decoder.cc",
diff --git a/media/gpu/v4l2/test/av1_decoder.cc b/media/gpu/v4l2/test/av1_decoder.cc
index 399e1cf2..8911ccf 100644
--- a/media/gpu/v4l2/test/av1_decoder.cc
+++ b/media/gpu/v4l2/test/av1_decoder.cc
@@ -7,6 +7,7 @@
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "media/filters/ivf_parser.h"
+#include "media/gpu/v4l2/test/av1_pix_fmt.h"
 
 namespace media {
 
diff --git a/media/gpu/v4l2/test/av1_decoder.h b/media/gpu/v4l2/test/av1_decoder.h
index 800c746..240f38a5 100644
--- a/media/gpu/v4l2/test/av1_decoder.h
+++ b/media/gpu/v4l2/test/av1_decoder.h
@@ -5,12 +5,12 @@
 #ifndef MEDIA_GPU_V4L2_TEST_AV1_DECODER_H_
 #define MEDIA_GPU_V4L2_TEST_AV1_DECODER_H_
 
-#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h"
 #include "media/gpu/v4l2/test/video_decoder.h"
 
 #include <set>
 
 #include "media/filters/ivf_parser.h"
+#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h"
 // For libgav1::ObuSequenceHeader. absl::optional demands ObuSequenceHeader to
 // fulfill std::is_trivially_constructible if it is forward-declared. But
 // ObuSequenceHeader doesn't.
@@ -22,18 +22,6 @@
 // base/logging.h for ChromeOS.
 #define ANALYZER_ALLOW_UNUSED(var) static_cast<void>(var);
 
-// TODO(stevecho): This is temporary until the change to define
-// V4L2_PIX_FMT_AV1_FRAME lands in videodev2.h.
-// https://patchwork.linuxtv.org/project/linux-media/patch/20210810220552.298140-2-daniel.almeida@collabora.com/
-#ifndef V4L2_PIX_FMT_AV1
-#define V4L2_PIX_FMT_AV1 v4l2_fourcc('A', 'V', '0', '1') /* AV1 */
-#endif
-#ifndef V4L2_PIX_FMT_AV1_FRAME
-#define V4L2_PIX_FMT_AV1_FRAME                        \
-  v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame \
-                                   */
-#endif
-
 namespace media {
 namespace v4l2_test {
 
diff --git a/media/gpu/v4l2/test/av1_pix_fmt.h b/media/gpu/v4l2/test/av1_pix_fmt.h
new file mode 100644
index 0000000..ca272b5
--- /dev/null
+++ b/media/gpu/v4l2/test/av1_pix_fmt.h
@@ -0,0 +1,20 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_V4L2_TEST_AV1_PIX_FMT_H_
+#define MEDIA_GPU_V4L2_TEST_AV1_PIX_FMT_H_
+
+// TODO(stevecho): This is temporary until the change to define
+// V4L2_PIX_FMT_AV1_FRAME lands in videodev2.h.
+// https://patchwork.linuxtv.org/project/linux-media/patch/20210810220552.298140-2-daniel.almeida@collabora.com/
+#ifndef V4L2_PIX_FMT_AV1
+#define V4L2_PIX_FMT_AV1 v4l2_fourcc('A', 'V', '0', '1') /* AV1 */
+#endif
+#ifndef V4L2_PIX_FMT_AV1_FRAME
+#define V4L2_PIX_FMT_AV1_FRAME                        \
+  v4l2_fourcc('A', 'V', '1', 'F') /* AV1 parsed frame \
+                                   */
+#endif
+
+#endif  // MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_
diff --git a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
index fbe3784c..fbfcb5c9 100644
--- a/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
+++ b/media/gpu/v4l2/test/v4l2_stateless_decoder.cc
@@ -18,6 +18,7 @@
 #include "media/base/video_types.h"
 #include "media/filters/ivf_parser.h"
 #include "media/gpu/v4l2/test/av1_decoder.h"
+#include "media/gpu/v4l2/test/av1_pix_fmt.h"
 #include "media/gpu/v4l2/test/video_decoder.h"
 #include "media/gpu/v4l2/test/vp9_decoder.h"
 
@@ -64,23 +65,6 @@
 
 }  // namespace
 
-// For stateless API, fourcc |VP9F| is needed instead of |VP90| for VP9 codec.
-// Fourcc |AV1F| is needed instead of |AV10| for AV1 codec.
-// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-compressed.html
-// Converts fourcc |VP90| or |AV01| from file header to fourcc |VP9F| or |AV1F|,
-// which is a format supported on driver.
-uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc) {
-  if (header_fourcc == V4L2_PIX_FMT_VP9) {
-    LOG(INFO) << "OUTPUT format mapped from VP90 to VP9F.";
-    return V4L2_PIX_FMT_VP9_FRAME;
-  } else if (header_fourcc == V4L2_PIX_FMT_AV1) {
-    LOG(INFO) << "OUTPUT format mapped from AV01 to AV1F.";
-    return V4L2_PIX_FMT_AV1_FRAME;
-  }
-
-  return header_fourcc;
-}
-
 // Computes the md5 of given I420 data |yuv_plane| and prints the md5 to stdout.
 // This functionality is needed for tast tests.
 void ComputeAndPrintMd5hash(const std::vector<char>& yuv_plane) {
@@ -108,7 +92,8 @@
   VLOG(1) << "Creating decoder with codec "
           << media::FourccToString(file_header.fourcc);
 
-  const auto driver_codec_fourcc = FileFourccToDriverFourcc(file_header.fourcc);
+  const auto driver_codec_fourcc =
+      media::v4l2_test::FileFourccToDriverFourcc(file_header.fourcc);
 
   if (driver_codec_fourcc == V4L2_PIX_FMT_AV1_FRAME) {
     return Av1Decoder::Create(std::move(ivf_parser), file_header);
diff --git a/media/gpu/v4l2/test/video_decoder.cc b/media/gpu/v4l2/test/video_decoder.cc
index c86241d..aedd3c7 100644
--- a/media/gpu/v4l2/test/video_decoder.cc
+++ b/media/gpu/v4l2/test/video_decoder.cc
@@ -4,8 +4,11 @@
 
 #include "media/gpu/v4l2/test/video_decoder.h"
 
+#include <linux/videodev2.h>
+
 #include "base/bits.h"
 #include "base/logging.h"
+#include "media/gpu/v4l2/test/av1_pix_fmt.h"
 
 namespace media {
 namespace v4l2_test {
@@ -93,6 +96,18 @@
 
 }  // namespace
 
+uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc) {
+  if (header_fourcc == V4L2_PIX_FMT_VP9) {
+    LOG(INFO) << "OUTPUT format mapped from VP90 to VP9F.";
+    return V4L2_PIX_FMT_VP9_FRAME;
+  } else if (header_fourcc == V4L2_PIX_FMT_AV1) {
+    LOG(INFO) << "OUTPUT format mapped from AV01 to AV1F.";
+    return V4L2_PIX_FMT_AV1_FRAME;
+  }
+
+  return header_fourcc;
+}
+
 VideoDecoder::VideoDecoder(std::unique_ptr<IvfParser> ivf_parser,
                            std::unique_ptr<V4L2IoctlShim> v4l2_ioctl,
                            std::unique_ptr<V4L2Queue> OUTPUT_queue,
diff --git a/media/gpu/v4l2/test/video_decoder.h b/media/gpu/v4l2/test/video_decoder.h
index abbf3c5a..718fd0dd 100644
--- a/media/gpu/v4l2/test/video_decoder.h
+++ b/media/gpu/v4l2/test/video_decoder.h
@@ -5,13 +5,19 @@
 #ifndef MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_
 #define MEDIA_GPU_V4L2_TEST_VIDEO_DECODER_H_
 
-#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h"
-
 #include "media/filters/ivf_parser.h"
+#include "media/gpu/v4l2/test/v4l2_ioctl_shim.h"
 
 namespace media {
 namespace v4l2_test {
 
+// For stateless API, fourcc |VP9F| is needed instead of |VP90| for VP9 codec.
+// Fourcc |AV1F| is needed instead of |AV10| for AV1 codec.
+// https://www.kernel.org/doc/html/latest/userspace-api/media/v4l/pixfmt-compressed.html
+// Converts fourcc |VP90| or |AV01| from file header to fourcc |VP9F| or |AV1F|,
+// which is a format supported on driver.
+uint32_t FileFourccToDriverFourcc(uint32_t header_fourcc);
+
 // VideoDecoder decodes encoded IVF streams using v4l2 ioctl calls.
 class VideoDecoder {
  public:
diff --git a/net/base/auth.cc b/net/base/auth.cc
index 3af2751..9f27cdd3 100644
--- a/net/base/auth.cc
+++ b/net/base/auth.cc
@@ -6,8 +6,7 @@
 
 namespace net {
 
-AuthChallengeInfo::AuthChallengeInfo() : is_proxy(false) {
-}
+AuthChallengeInfo::AuthChallengeInfo() = default;
 
 AuthChallengeInfo::AuthChallengeInfo(const AuthChallengeInfo& other) = default;
 
diff --git a/net/base/auth.h b/net/base/auth.h
index 19676512..6bf76347 100644
--- a/net/base/auth.h
+++ b/net/base/auth.h
@@ -26,7 +26,7 @@
   bool MatchesExceptPath(const AuthChallengeInfo& other) const;
 
   // Whether this came from a server or a proxy.
-  bool is_proxy;
+  bool is_proxy = false;
 
   // The service issuing the challenge.
   url::SchemeHostPort challenger;
diff --git a/net/base/directory_lister.cc b/net/base/directory_lister.cc
index 3f0dce8..0882163 100644
--- a/net/base/directory_lister.cc
+++ b/net/base/directory_lister.cc
@@ -97,8 +97,7 @@
     : dir_(dir),
       type_(type),
       origin_task_runner_(base::SequencedTaskRunnerHandle::Get().get()),
-      lister_(lister),
-      cancelled_(0) {
+      lister_(lister) {
   DCHECK(lister_);
 }
 
diff --git a/net/base/directory_lister.h b/net/base/directory_lister.h
index 9f87940..3701a5a 100644
--- a/net/base/directory_lister.h
+++ b/net/base/directory_lister.h
@@ -124,7 +124,7 @@
     // Set to 1 on cancellation. Used both to abort listing files early on the
     // worker pool thread for performance reasons and to ensure |lister_| isn't
     // called after cancellation on the origin thread.
-    base::subtle::Atomic32 cancelled_;
+    base::subtle::Atomic32 cancelled_ = 0;
   };
 
   // Call into the corresponding DirectoryListerDelegate. Must not be called
diff --git a/net/base/directory_lister_unittest.cc b/net/base/directory_lister_unittest.cc
index 9d5aedf..3b6ac1c 100644
--- a/net/base/directory_lister_unittest.cc
+++ b/net/base/directory_lister_unittest.cc
@@ -36,12 +36,7 @@
 class ListerDelegate : public DirectoryLister::DirectoryListerDelegate {
  public:
   explicit ListerDelegate(DirectoryLister::ListingType type)
-      : cancel_lister_on_list_file_(false),
-        cancel_lister_on_list_done_(false),
-        lister_(nullptr),
-        done_(false),
-        error_(-1),
-        type_(type) {}
+      : lister_(nullptr), type_(type) {}
 
   // When set to true, this signals that the directory list operation should be
   // cancelled (And the run loop quit) in the first call to OnListFile.
@@ -114,16 +109,16 @@
   bool done() const { return done_; }
 
  private:
-  bool cancel_lister_on_list_file_;
-  bool cancel_lister_on_list_done_;
+  bool cancel_lister_on_list_file_ = false;
+  bool cancel_lister_on_list_done_ = false;
 
   // This is owned by the individual tests, rather than the ListerDelegate.
   raw_ptr<DirectoryLister> lister_;
 
   base::RunLoop run_loop;
 
-  bool done_;
-  int error_;
+  bool done_ = false;
+  int error_ = -1;
   DirectoryLister::ListingType type_;
 
   std::vector<base::FileEnumerator::FileInfo> file_list_;
@@ -134,9 +129,7 @@
 
 class DirectoryListerTest : public PlatformTest, public WithTaskEnvironment {
  public:
-  DirectoryListerTest()
-      : total_created_file_system_objects_in_temp_root_dir_(0),
-        created_file_system_objects_in_temp_root_dir_(0) {}
+  DirectoryListerTest() = default;
 
   void SetUp() override {
     // Randomly create a directory structure of depth 3 in a temporary root
@@ -188,9 +181,9 @@
  private:
   // Number of files and directories created in SetUp, excluding
   // |temp_root_dir_| itself.  Includes all nested directories and their files.
-  int total_created_file_system_objects_in_temp_root_dir_;
+  int total_created_file_system_objects_in_temp_root_dir_ = 0;
   // Number of files and directories created directly in |temp_root_dir_|.
-  int created_file_system_objects_in_temp_root_dir_;
+  int created_file_system_objects_in_temp_root_dir_ = 0;
 
   base::ScopedTempDir temp_root_dir_;
 };
diff --git a/net/base/elements_upload_data_stream.cc b/net/base/elements_upload_data_stream.cc
index a5f3189..1f5d616 100644
--- a/net/base/elements_upload_data_stream.cc
+++ b/net/base/elements_upload_data_stream.cc
@@ -19,9 +19,7 @@
     std::vector<std::unique_ptr<UploadElementReader>> element_readers,
     int64_t identifier)
     : UploadDataStream(false, identifier),
-      element_readers_(std::move(element_readers)),
-      element_index_(0),
-      read_error_(OK) {}
+      element_readers_(std::move(element_readers)) {}
 
 ElementsUploadDataStream::~ElementsUploadDataStream() = default;
 
diff --git a/net/base/elements_upload_data_stream.h b/net/base/elements_upload_data_stream.h
index 0806a9e..d2e7388 100644
--- a/net/base/elements_upload_data_stream.h
+++ b/net/base/elements_upload_data_stream.h
@@ -13,6 +13,7 @@
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "net/base/net_errors.h"
 #include "net/base/net_export.h"
 #include "net/base/upload_data_stream.h"
 
@@ -77,10 +78,10 @@
   // Index of the current upload element (i.e. the element currently being
   // read). The index is used as a cursor to iterate over elements in
   // |upload_data_|.
-  size_t element_index_;
+  size_t element_index_ = 0;
 
   // Set to actual error if read fails, otherwise set to net::OK.
-  int read_error_;
+  int read_error_ = OK;
 
   base::WeakPtrFactory<ElementsUploadDataStream> weak_ptr_factory_{this};
 };
diff --git a/net/base/elements_upload_data_stream_unittest.cc b/net/base/elements_upload_data_stream_unittest.cc
index af44f0a..b586bf0 100644
--- a/net/base/elements_upload_data_stream_unittest.cc
+++ b/net/base/elements_upload_data_stream_unittest.cc
@@ -71,9 +71,7 @@
   MockUploadElementReader(int content_length, bool is_in_memory)
       : content_length_(content_length),
         bytes_remaining_(content_length),
-        is_in_memory_(is_in_memory),
-        init_result_(OK),
-        read_result_(OK) {}
+        is_in_memory_(is_in_memory) {}
 
   ~MockUploadElementReader() override = default;
 
@@ -134,10 +132,10 @@
   bool is_in_memory_;
 
   // Result value returned from Init().
-  int init_result_;
+  int init_result_ = OK;
 
   // Result value returned from Read().
-  int read_result_;
+  int read_result_ = OK;
 };
 
 }  // namespace
diff --git a/net/base/file_stream_unittest.cc b/net/base/file_stream_unittest.cc
index a05b8e5..59194e81 100644
--- a/net/base/file_stream_unittest.cc
+++ b/net/base/file_stream_unittest.cc
@@ -502,10 +502,7 @@
                                   int* total_bytes_written,
                                   int* total_bytes_read,
                                   std::string* data_read)
-      : result_(0),
-        have_result_(false),
-        waiting_for_result_(false),
-        stream_(stream),
+      : stream_(stream),
         total_bytes_written_(total_bytes_written),
         total_bytes_read_(total_bytes_read),
         data_read_(data_read),
@@ -588,9 +585,9 @@
       base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
-  int result_;
-  bool have_result_;
-  bool waiting_for_result_;
+  int result_ = 0;
+  bool have_result_ = false;
+  bool waiting_for_result_ = false;
   raw_ptr<FileStream> stream_;
   raw_ptr<int> total_bytes_written_;
   raw_ptr<int> total_bytes_read_;
@@ -645,10 +642,7 @@
 class TestWriteCloseCompletionCallback {
  public:
   TestWriteCloseCompletionCallback(FileStream* stream, int* total_bytes_written)
-      : result_(0),
-        have_result_(false),
-        waiting_for_result_(false),
-        stream_(stream),
+      : stream_(stream),
         total_bytes_written_(total_bytes_written),
         drainable_(
             base::MakeRefCounted<DrainableIOBuffer>(CreateTestDataBuffer(),
@@ -699,9 +693,9 @@
       base::RunLoop::QuitCurrentWhenIdleDeprecated();
   }
 
-  int result_;
-  bool have_result_;
-  bool waiting_for_result_;
+  int result_ = 0;
+  bool have_result_ = false;
+  bool waiting_for_result_ = false;
   raw_ptr<FileStream> stream_;
   raw_ptr<int> total_bytes_written_;
   scoped_refptr<DrainableIOBuffer> drainable_;
diff --git a/net/base/host_mapping_rules.cc b/net/base/host_mapping_rules.cc
index de2fd4d..3cd8027 100644
--- a/net/base/host_mapping_rules.cc
+++ b/net/base/host_mapping_rules.cc
@@ -21,11 +21,11 @@
 namespace net {
 
 struct HostMappingRules::MapRule {
-  MapRule() : replacement_port(-1) {}
+  MapRule() = default;
 
   std::string hostname_pattern;
   std::string replacement_hostname;
-  int replacement_port;
+  int replacement_port = -1;
 };
 
 struct HostMappingRules::ExclusionRule {
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc
index cb133519..78d4cf4 100644
--- a/net/base/io_buffer.cc
+++ b/net/base/io_buffer.cc
@@ -102,11 +102,7 @@
   data_ = nullptr;
 }
 
-GrowableIOBuffer::GrowableIOBuffer()
-    : IOBuffer(),
-      capacity_(0),
-      offset_(0) {
-}
+GrowableIOBuffer::GrowableIOBuffer() = default;
 
 void GrowableIOBuffer::SetCapacity(int capacity) {
   DCHECK_GE(capacity, 0);
diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h
index 047c9f4..2de7d9e 100644
--- a/net/base/io_buffer.h
+++ b/net/base/io_buffer.h
@@ -215,8 +215,8 @@
   ~GrowableIOBuffer() override;
 
   std::unique_ptr<char, base::FreeDeleter> real_data_;
-  int capacity_;
-  int offset_;
+  int capacity_ = 0;
+  int offset_ = 0;
 };
 
 // This versions allows a pickle to be used as the storage for a write-style
diff --git a/net/base/load_timing_info.cc b/net/base/load_timing_info.cc
index 5ce74ca..7471f5c5 100644
--- a/net/base/load_timing_info.cc
+++ b/net/base/load_timing_info.cc
@@ -12,8 +12,7 @@
 
 LoadTimingInfo::ConnectTiming::~ConnectTiming() = default;
 
-LoadTimingInfo::LoadTimingInfo()
-    : socket_reused(false), socket_log_id(NetLogSource::kInvalidId) {}
+LoadTimingInfo::LoadTimingInfo() : socket_log_id(NetLogSource::kInvalidId) {}
 
 LoadTimingInfo::LoadTimingInfo(const LoadTimingInfo& other) = default;
 
diff --git a/net/base/load_timing_info.h b/net/base/load_timing_info.h
index 759559b..98e1225 100644
--- a/net/base/load_timing_info.h
+++ b/net/base/load_timing_info.h
@@ -119,7 +119,7 @@
   // Responding to a proxy AUTH challenge is never considered to be reusing a
   // socket, since a connection to the host wasn't established when the
   // challenge was received.
-  bool socket_reused;
+  bool socket_reused = false;
 
   // Unique socket ID, can be used to identify requests served by the same
   // socket.  For connections tunnelled over SPDY proxies, this is the ID of
diff --git a/net/base/lookup_string_in_fixed_set.cc b/net/base/lookup_string_in_fixed_set.cc
index b726fb9..8b08b27 100644
--- a/net/base/lookup_string_in_fixed_set.cc
+++ b/net/base/lookup_string_in_fixed_set.cc
@@ -71,7 +71,7 @@
 
 FixedSetIncrementalLookup::FixedSetIncrementalLookup(const unsigned char* graph,
                                                      size_t length)
-    : pos_(graph), end_(graph + length), pos_is_label_character_(false) {}
+    : pos_(graph), end_(graph + length) {}
 
 FixedSetIncrementalLookup::FixedSetIncrementalLookup(
     const FixedSetIncrementalLookup& other) = default;
diff --git a/net/base/lookup_string_in_fixed_set.h b/net/base/lookup_string_in_fixed_set.h
index f27c704..9d6e4ba 100644
--- a/net/base/lookup_string_in_fixed_set.h
+++ b/net/base/lookup_string_in_fixed_set.h
@@ -152,7 +152,7 @@
   // Contains the current decoder state. If true, |pos_| points to a label
   // character or a return code. If false, |pos_| points to a sequence of
   // offsets that indicate the child nodes of the current state.
-  bool pos_is_label_character_;
+  bool pos_is_label_character_ = false;
 };
 
 }  // namespace net
diff --git a/net/base/mock_network_change_notifier.cc b/net/base/mock_network_change_notifier.cc
index 952f7c8d..427bf4f 100644
--- a/net/base/mock_network_change_notifier.cc
+++ b/net/base/mock_network_change_notifier.cc
@@ -104,9 +104,6 @@
     std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier)
     : NetworkChangeNotifier(NetworkChangeCalculatorParams(),
                             dns_config_notifier.get()),
-      force_network_handles_supported_(false),
-      connection_type_(CONNECTION_UNKNOWN),
-      connection_cost_(CONNECTION_COST_UNKNOWN),
       dns_config_notifier_(std::move(dns_config_notifier)) {}
 
 ScopedMockNetworkChangeNotifier::ScopedMockNetworkChangeNotifier()
diff --git a/net/base/mock_network_change_notifier.h b/net/base/mock_network_change_notifier.h
index 24e01598..67295ce 100644
--- a/net/base/mock_network_change_notifier.h
+++ b/net/base/mock_network_change_notifier.h
@@ -82,9 +82,9 @@
   MockNetworkChangeNotifier(
       std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier);
 
-  bool force_network_handles_supported_;
-  ConnectionType connection_type_;
-  ConnectionCost connection_cost_;
+  bool force_network_handles_supported_ = false;
+  ConnectionType connection_type_ = CONNECTION_UNKNOWN;
+  ConnectionCost connection_cost_ = CONNECTION_COST_UNKNOWN;
   bool use_default_connection_cost_implementation_ = false;
   NetworkChangeNotifier::NetworkList connected_networks_;
   std::unique_ptr<SystemDnsConfigChangeNotifier> dns_config_notifier_;
diff --git a/net/base/network_change_notifier.cc b/net/base/network_change_notifier.cc
index ce8fad5e4..1dd4055 100644
--- a/net/base/network_change_notifier.cc
+++ b/net/base/network_change_notifier.cc
@@ -107,10 +107,7 @@
       public IPAddressObserver {
  public:
   explicit NetworkChangeCalculator(const NetworkChangeCalculatorParams& params)
-      : params_(params),
-        have_announced_(false),
-        last_announced_connection_type_(CONNECTION_NONE),
-        pending_connection_type_(CONNECTION_NONE) {
+      : params_(params) {
     DCHECK(g_network_change_notifier);
     AddConnectionTypeObserver(this);
     AddConnectionCostObserver(this);
@@ -180,11 +177,11 @@
   const NetworkChangeCalculatorParams params_;
 
   // Indicates if NotifyObserversOfNetworkChange has been called yet.
-  bool have_announced_;
+  bool have_announced_ = false;
   // Last value passed to NotifyObserversOfNetworkChange.
-  ConnectionType last_announced_connection_type_;
+  ConnectionType last_announced_connection_type_ = CONNECTION_NONE;
   // Value to pass to NotifyObserversOfNetworkChange when Notify is called.
-  ConnectionType pending_connection_type_;
+  ConnectionType pending_connection_type_ = CONNECTION_NONE;
   // Used to delay notifications so duplicates can be combined.
   base::OneShotTimer timer_;
 
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 096d57e6..5a21d36 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -44,7 +44,8 @@
   void OnLinkChanged();
   // Used to detect online/offline state and IP address changes.
   internal::AddressTrackerLinux address_tracker_;
-  NetworkChangeNotifier::ConnectionType last_type_;
+  NetworkChangeNotifier::ConnectionType last_type_ =
+      NetworkChangeNotifier::CONNECTION_NONE;
 };
 
 NetworkChangeNotifierLinux::BlockingThreadObjects::BlockingThreadObjects(
@@ -57,8 +58,7 @@
               &NetworkChangeNotifierLinux::BlockingThreadObjects::OnLinkChanged,
               base::Unretained(this)),
           base::DoNothing(),
-          ignored_interfaces),
-      last_type_(NetworkChangeNotifier::CONNECTION_NONE) {}
+          ignored_interfaces) {}
 
 void NetworkChangeNotifierLinux::BlockingThreadObjects::Init() {
   address_tracker_.Init();
diff --git a/net/base/prioritized_dispatcher_unittest.cc b/net/base/prioritized_dispatcher_unittest.cc
index ae9effc..0f5ba3e 100644
--- a/net/base/prioritized_dispatcher_unittest.cc
+++ b/net/base/prioritized_dispatcher_unittest.cc
@@ -41,11 +41,7 @@
             char tag,
             Priority priority,
             std::string* log)
-        : dispatcher_(dispatcher),
-          tag_(tag),
-          priority_(priority),
-          running_(false),
-          log_(log) {}
+        : dispatcher_(dispatcher), tag_(tag), priority_(priority), log_(log) {}
 
     bool running() const {
       return running_;
@@ -134,7 +130,7 @@
     Priority priority_;
 
     PrioritizedDispatcher::Handle handle_;
-    bool running_;
+    bool running_ = false;
 
     raw_ptr<std::string> log_;
   };
diff --git a/net/base/upload_data_stream.cc b/net/base/upload_data_stream.cc
index cccaedb0..c282bd2 100644
--- a/net/base/upload_data_stream.cc
+++ b/net/base/upload_data_stream.cc
@@ -35,13 +35,7 @@
 }  // namespace
 
 UploadDataStream::UploadDataStream(bool is_chunked, int64_t identifier)
-    : total_size_(0),
-      current_position_(0),
-      identifier_(identifier),
-      is_chunked_(is_chunked),
-      initialized_successfully_(false),
-      is_eof_(false) {
-}
+    : identifier_(identifier), is_chunked_(is_chunked) {}
 
 UploadDataStream::~UploadDataStream() = default;
 
diff --git a/net/base/upload_data_stream.h b/net/base/upload_data_stream.h
index a1b6bd2..89eeef08 100644
--- a/net/base/upload_data_stream.h
+++ b/net/base/upload_data_stream.h
@@ -133,17 +133,17 @@
   // at least once before every call to InitInternal.
   virtual void ResetInternal() = 0;
 
-  uint64_t total_size_;
-  uint64_t current_position_;
+  uint64_t total_size_ = 0;
+  uint64_t current_position_ = 0;
 
   const int64_t identifier_;
 
   const bool is_chunked_;
 
   // True if the initialization was successful.
-  bool initialized_successfully_;
+  bool initialized_successfully_ = false;
 
-  bool is_eof_;
+  bool is_eof_ = false;
 
   CompletionOnceCallback callback_;
 
diff --git a/net/cert/caching_cert_verifier.cc b/net/cert/caching_cert_verifier.cc
index ee2ec1d9..d2c1ead3 100644
--- a/net/cert/caching_cert_verifier.cc
+++ b/net/cert/caching_cert_verifier.cc
@@ -23,11 +23,7 @@
 }  // namespace
 
 CachingCertVerifier::CachingCertVerifier(std::unique_ptr<CertVerifier> verifier)
-    : verifier_(std::move(verifier)),
-      config_id_(0u),
-      cache_(kMaxCacheEntries),
-      requests_(0u),
-      cache_hits_(0u) {
+    : verifier_(std::move(verifier)), cache_(kMaxCacheEntries) {
   CertDatabase::GetInstance()->AddObserver(this);
 }
 
@@ -72,7 +68,7 @@
   ClearCache();
 }
 
-CachingCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {}
+CachingCertVerifier::CachedResult::CachedResult() = default;
 
 CachingCertVerifier::CachedResult::~CachedResult() = default;
 
diff --git a/net/cert/caching_cert_verifier.h b/net/cert/caching_cert_verifier.h
index 8fc1afa..ce06e6eb 100644
--- a/net/cert/caching_cert_verifier.h
+++ b/net/cert/caching_cert_verifier.h
@@ -67,7 +67,7 @@
     CachedResult();
     ~CachedResult();
 
-    int error;                // The return value of CertVerifier::Verify.
+    int error = ERR_FAILED;   // The return value of CertVerifier::Verify.
     CertVerifyResult result;  // The output of CertVerifier::Verify.
   };
 
@@ -129,11 +129,11 @@
 
   std::unique_ptr<CertVerifier> verifier_;
 
-  uint32_t config_id_;
+  uint32_t config_id_ = 0u;
   CertVerificationCache cache_;
 
-  uint64_t requests_;
-  uint64_t cache_hits_;
+  uint64_t requests_ = 0u;
+  uint64_t cache_hits_ = 0u;
 };
 
 }  // namespace net
diff --git a/net/cert/coalescing_cert_verifier.cc b/net/cert/coalescing_cert_verifier.cc
index a7c003ee..a8878f0 100644
--- a/net/cert/coalescing_cert_verifier.cc
+++ b/net/cert/coalescing_cert_verifier.cc
@@ -380,10 +380,7 @@
 
 CoalescingCertVerifier::CoalescingCertVerifier(
     std::unique_ptr<CertVerifier> verifier)
-    : verifier_(std::move(verifier)),
-      config_id_(0),
-      requests_(0),
-      inflight_joins_(0) {}
+    : verifier_(std::move(verifier)) {}
 
 CoalescingCertVerifier::~CoalescingCertVerifier() = default;
 
diff --git a/net/cert/coalescing_cert_verifier.h b/net/cert/coalescing_cert_verifier.h
index 40686b1..1625a86b7 100644
--- a/net/cert/coalescing_cert_verifier.h
+++ b/net/cert/coalescing_cert_verifier.h
@@ -70,9 +70,9 @@
 
   std::unique_ptr<CertVerifier> verifier_;
 
-  uint32_t config_id_;
-  uint64_t requests_;
-  uint64_t inflight_joins_;
+  uint32_t config_id_ = 0;
+  uint64_t requests_ = 0;
+  uint64_t inflight_joins_ = 0;
 };
 
 }  // namespace net
diff --git a/net/cert/crl_set.cc b/net/cert/crl_set.cc
index 2579030..cc9e6c5 100644
--- a/net/cert/crl_set.cc
+++ b/net/cert/crl_set.cc
@@ -197,10 +197,7 @@
 
 }  // namespace
 
-CRLSet::CRLSet()
-    : sequence_(0),
-      not_after_(0) {
-}
+CRLSet::CRLSet() = default;
 
 CRLSet::~CRLSet() = default;
 
diff --git a/net/cert/crl_set.h b/net/cert/crl_set.h
index f260a060..b629ea46 100644
--- a/net/cert/crl_set.h
+++ b/net/cert/crl_set.h
@@ -114,10 +114,10 @@
 
   friend class base::RefCountedThreadSafe<CRLSet>;
 
-  uint32_t sequence_;
+  uint32_t sequence_ = 0;
   // not_after_ contains the time, in UNIX epoch seconds, after which the
   // CRLSet should be considered stale, or 0 if no such time was given.
-  uint64_t not_after_;
+  uint64_t not_after_ = 0;
   // crls_ is a map from the SHA-256 hash of an X.501 subject name to a list
   // of revoked serial numbers.
   CRLList crls_;
diff --git a/net/cert/ct_log_verifier.cc b/net/cert/ct_log_verifier.cc
index 5c46e05..56b41a54 100644
--- a/net/cert/ct_log_verifier.cc
+++ b/net/cert/ct_log_verifier.cc
@@ -67,10 +67,7 @@
 }
 
 CTLogVerifier::CTLogVerifier(std::string description)
-    : description_(std::move(description)),
-      hash_algorithm_(ct::DigitallySigned::HASH_ALGO_NONE),
-      signature_algorithm_(ct::DigitallySigned::SIG_ALGO_ANONYMOUS),
-      public_key_(nullptr) {}
+    : description_(std::move(description)), public_key_(nullptr) {}
 
 bool CTLogVerifier::Verify(const ct::SignedEntryData& entry,
                            const ct::SignedCertificateTimestamp& sct) const {
diff --git a/net/cert/ct_log_verifier.h b/net/cert/ct_log_verifier.h
index fafc972..69ea252 100644
--- a/net/cert/ct_log_verifier.h
+++ b/net/cert/ct_log_verifier.h
@@ -91,8 +91,10 @@
 
   std::string key_id_;
   std::string description_;
-  ct::DigitallySigned::HashAlgorithm hash_algorithm_;
-  ct::DigitallySigned::SignatureAlgorithm signature_algorithm_;
+  ct::DigitallySigned::HashAlgorithm hash_algorithm_ =
+      ct::DigitallySigned::HASH_ALGO_NONE;
+  ct::DigitallySigned::SignatureAlgorithm signature_algorithm_ =
+      ct::DigitallySigned::SIG_ALGO_ANONYMOUS;
 
   raw_ptr<EVP_PKEY> public_key_;
 };
diff --git a/net/cert/mock_cert_verifier.cc b/net/cert/mock_cert_verifier.cc
index 25d5531f..e47554e2 100644
--- a/net/cert/mock_cert_verifier.cc
+++ b/net/cert/mock_cert_verifier.cc
@@ -81,8 +81,7 @@
   base::WeakPtrFactory<MockRequest> weak_factory_{this};
 };
 
-MockCertVerifier::MockCertVerifier()
-    : default_result_(ERR_CERT_INVALID), async_(false) {}
+MockCertVerifier::MockCertVerifier() = default;
 
 MockCertVerifier::~MockCertVerifier() {
   // Reset the callbacks for any outstanding MockRequests to fulfill the
diff --git a/net/cert/mock_cert_verifier.h b/net/cert/mock_cert_verifier.h
index f653fe37..de9e42e 100644
--- a/net/cert/mock_cert_verifier.h
+++ b/net/cert/mock_cert_verifier.h
@@ -70,9 +70,9 @@
 
   int VerifyImpl(const RequestParams& params, CertVerifyResult* verify_result);
 
-  int default_result_;
+  int default_result_ = ERR_CERT_INVALID;
   RuleList rules_;
-  bool async_;
+  bool async_ = false;
 
   base::OnceClosureList request_list_;
 };
diff --git a/net/cert/mock_client_cert_verifier.cc b/net/cert/mock_client_cert_verifier.cc
index 4de56a5..3b23e51 100644
--- a/net/cert/mock_client_cert_verifier.cc
+++ b/net/cert/mock_client_cert_verifier.cc
@@ -18,8 +18,7 @@
   int rv;
 };
 
-MockClientCertVerifier::MockClientCertVerifier()
-    : default_result_(ERR_CERT_INVALID) {}
+MockClientCertVerifier::MockClientCertVerifier() = default;
 
 MockClientCertVerifier::~MockClientCertVerifier() = default;
 
diff --git a/net/cert/mock_client_cert_verifier.h b/net/cert/mock_client_cert_verifier.h
index 81026b7..166643f7 100644
--- a/net/cert/mock_client_cert_verifier.h
+++ b/net/cert/mock_client_cert_verifier.h
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "net/base/completion_once_callback.h"
+#include "net/base/net_errors.h"
 #include "net/cert/client_cert_verifier.h"
 
 namespace net {
@@ -45,7 +46,7 @@
   struct Rule;
   typedef std::list<Rule> RuleList;
 
-  int default_result_;
+  int default_result_ = ERR_CERT_INVALID;
   RuleList rules_;
 };
 
diff --git a/net/cert/signed_certificate_timestamp.cc b/net/cert/signed_certificate_timestamp.cc
index 4b2567b..aa33089 100644
--- a/net/cert/signed_certificate_timestamp.cc
+++ b/net/cert/signed_certificate_timestamp.cc
@@ -28,8 +28,7 @@
   return lhs->version < rhs->version;
 }
 
-SignedCertificateTimestamp::SignedCertificateTimestamp()
-    : version(V1), origin(SCT_EMBEDDED) {}
+SignedCertificateTimestamp::SignedCertificateTimestamp() = default;
 
 SignedCertificateTimestamp::~SignedCertificateTimestamp() = default;
 
@@ -78,7 +77,7 @@
   return sct;
 }
 
-SignedEntryData::SignedEntryData() : type(LOG_ENTRY_TYPE_X509) {}
+SignedEntryData::SignedEntryData() = default;
 
 SignedEntryData::~SignedEntryData() = default;
 
@@ -88,8 +87,7 @@
   tbs_certificate.clear();
 }
 
-DigitallySigned::DigitallySigned()
-    : hash_algorithm(HASH_ALGO_NONE), signature_algorithm(SIG_ALGO_ANONYMOUS) {}
+DigitallySigned::DigitallySigned() = default;
 
 DigitallySigned::~DigitallySigned() = default;
 
diff --git a/net/cert/signed_certificate_timestamp.h b/net/cert/signed_certificate_timestamp.h
index 5378cc1c..50d5a02a 100644
--- a/net/cert/signed_certificate_timestamp.h
+++ b/net/cert/signed_certificate_timestamp.h
@@ -48,7 +48,7 @@
   ~SignedEntryData();
   void Reset();
 
-  Type type;
+  Type type = LOG_ENTRY_TYPE_X509;
 
   // Set if type == LOG_ENTRY_TYPE_X509
   std::string leaf_certificate;
@@ -87,8 +87,8 @@
       HashAlgorithm other_hash_algorithm,
       SignatureAlgorithm other_signature_algorithm) const;
 
-  HashAlgorithm hash_algorithm;
-  SignatureAlgorithm signature_algorithm;
+  HashAlgorithm hash_algorithm = HASH_ALGO_NONE;
+  SignatureAlgorithm signature_algorithm = SIG_ALGO_ANONYMOUS;
   // 'signature' field.
   std::string signature_data;
 };
@@ -128,12 +128,12 @@
   static scoped_refptr<SignedCertificateTimestamp> CreateFromPickle(
       base::PickleIterator* iter);
 
-  Version version;
+  Version version = V1;
   std::string log_id;
   base::Time timestamp;
   std::string extensions;
   DigitallySigned signature;
-  Origin origin;
+  Origin origin = SCT_EMBEDDED;
   // The log description is not one of the SCT fields, but a user-readable
   // name defined alongside the log key. It should not participate
   // in equality checks as the log's description could change while
diff --git a/net/cert_net/cert_net_fetcher_url_request.cc b/net/cert_net/cert_net_fetcher_url_request.cc
index 8819618..e570758 100644
--- a/net/cert_net/cert_net_fetcher_url_request.cc
+++ b/net/cert_net/cert_net_fetcher_url_request.cc
@@ -295,8 +295,8 @@
   bool operator<(const RequestParams& other) const;
 
   GURL url;
-  HttpMethod http_method;
-  size_t max_response_bytes;
+  HttpMethod http_method = HTTP_METHOD_GET;
+  size_t max_response_bytes = 0;
 
   // If set to a value <= 0 then means "no timeout".
   base::TimeDelta timeout;
@@ -304,8 +304,7 @@
   // IMPORTANT: When adding fields to this structure, update operator<().
 };
 
-CertNetFetcherURLRequest::RequestParams::RequestParams()
-    : http_method(HTTP_METHOD_GET), max_response_bytes(0) {}
+CertNetFetcherURLRequest::RequestParams::RequestParams() = default;
 
 bool CertNetFetcherURLRequest::RequestParams::operator<(
     const RequestParams& other) const {
diff --git a/net/cert_net/cert_net_fetcher_url_request_unittest.cc b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
index 3def9a1..08092a4a 100644
--- a/net/cert_net/cert_net_fetcher_url_request_unittest.cc
+++ b/net/cert_net/cert_net_fetcher_url_request_unittest.cc
@@ -235,8 +235,7 @@
     : public CertNetFetcherURLRequestTest,
       public WithTaskEnvironment {
  public:
-  CertNetFetcherURLRequestTestWithSecureDnsInterceptor()
-      : invoked_interceptor_(false) {}
+  CertNetFetcherURLRequestTestWithSecureDnsInterceptor() = default;
 
   void SetUp() override {
     URLRequestFilter::GetInstance()->AddHostnameInterceptor(
@@ -249,7 +248,7 @@
   bool invoked_interceptor() { return invoked_interceptor_; }
 
  private:
-  bool invoked_interceptor_;
+  bool invoked_interceptor_ = false;
 };
 
 // Helper to start an AIA fetch using default parameters.
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index 8555811..12de7b5 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -72,7 +72,7 @@
 
 class CookieTestCallback {
  public:
-  CookieTestCallback() : has_run_(false) {}
+  CookieTestCallback() = default;
 
  protected:
   void WaitForCallback() {
@@ -88,7 +88,7 @@
 
   void Run() { has_run_ = true; }
 
-  bool has_run_;
+  bool has_run_ = false;
 };
 
 class SetCookieCallback : public CookieTestCallback {
diff --git a/net/cookies/cookie_monster_store_test.cc b/net/cookies/cookie_monster_store_test.cc
index 3812429..1bc8e95 100644
--- a/net/cookies/cookie_monster_store_test.cc
+++ b/net/cookies/cookie_monster_store_test.cc
@@ -30,8 +30,7 @@
 CookieStoreCommand::CookieStoreCommand(CookieStoreCommand&& other) = default;
 CookieStoreCommand::~CookieStoreCommand() = default;
 
-MockPersistentCookieStore::MockPersistentCookieStore()
-    : store_load_commands_(false), load_return_value_(true), loaded_(false) {}
+MockPersistentCookieStore::MockPersistentCookieStore() = default;
 
 void MockPersistentCookieStore::SetLoadExpectation(
     bool return_value,
@@ -135,9 +134,7 @@
   out_list->push_back(std::move(cookie));
 }
 
-MockSimplePersistentCookieStore::MockSimplePersistentCookieStore()
-    : loaded_(false) {
-}
+MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() = default;
 
 void MockSimplePersistentCookieStore::Load(
     LoadedCallback loaded_callback,
diff --git a/net/cookies/cookie_monster_store_test.h b/net/cookies/cookie_monster_store_test.h
index 8f3b96a..6250ebb 100644
--- a/net/cookies/cookie_monster_store_test.h
+++ b/net/cookies/cookie_monster_store_test.h
@@ -119,14 +119,14 @@
  private:
   CommandList commands_;
 
-  bool store_load_commands_;
+  bool store_load_commands_ = false;
 
   // Deferred result to use when Load() is called.
-  bool load_return_value_;
+  bool load_return_value_ = true;
   std::vector<std::unique_ptr<CanonicalCookie>> load_result_;
   // Indicates if the store has been fully loaded to avoid returning duplicate
   // cookies.
-  bool loaded_;
+  bool loaded_ = false;
 };
 
 // Helper to build a single CanonicalCookie.
@@ -177,7 +177,7 @@
 
   // Indicates if the store has been fully loaded to avoid return duplicate
   // cookies in subsequent load requests
-  bool loaded_;
+  bool loaded_ = false;
 };
 
 // Helper function for creating a CookieMonster backed by a
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 6982534..31c9538 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -75,7 +75,6 @@
     : cookie_monster_(new CookieMonster(nullptr /* store */,
                                         nullptr /* netlog */,
                                         false /* first_party_sets_enabled */)),
-      did_run_(false),
       result_(CookieAccessResult(CookieInclusionStatus(
           CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE))) {}
 
@@ -216,7 +215,7 @@
 //
 // FlushablePersistentStore
 //
-FlushablePersistentStore::FlushablePersistentStore() : flush_count_(0) {}
+FlushablePersistentStore::FlushablePersistentStore() = default;
 
 void FlushablePersistentStore::Load(LoadedCallback loaded_callback,
                                     const NetLogWithSource& /* net_log */) {
@@ -259,7 +258,7 @@
 //
 // CallbackCounter
 //
-CallbackCounter::CallbackCounter() : callback_count_(0) {}
+CallbackCounter::CallbackCounter() = default;
 
 void CallbackCounter::Callback() {
   base::AutoLock lock(callback_count_lock_);
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index fcb3997..03ecacf 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -119,7 +119,7 @@
   std::unique_ptr<CookieMonster> cookie_monster_;
   DelayedCookieMonsterChangeDispatcher change_dispatcher_;
 
-  bool did_run_;
+  bool did_run_ = false;
   CookieAccessResult result_;
   std::string cookie_;
   std::string cookie_line_;
@@ -169,7 +169,7 @@
  private:
   ~FlushablePersistentStore() override;
 
-  int flush_count_;
+  int flush_count_ = 0;
   base::Lock flush_count_lock_;  // Protects |flush_count_|.
 };
 
@@ -184,7 +184,7 @@
   friend class base::RefCountedThreadSafe<CallbackCounter>;
   ~CallbackCounter();
 
-  int callback_count_;
+  int callback_count_ = 0;
   base::Lock callback_count_lock_;  // Protects |callback_count_|.
 };
 
diff --git a/net/disk_cache/blockfile/backend_impl.cc b/net/disk_cache/blockfile/backend_impl.cc
index 058d610..171551d 100644
--- a/net/disk_cache/blockfile/backend_impl.cc
+++ b/net/disk_cache/blockfile/backend_impl.cc
@@ -158,7 +158,6 @@
       background_queue_(this, FallbackToInternalIfNull(cache_thread)),
       path_(path),
       block_files_(path),
-      mask_(0),
       user_flags_(0),
       net_log_(net_log) {
   TRACE_EVENT0("disk_cache", "BackendImpl::BackendImpl");
diff --git a/net/disk_cache/blockfile/entry_impl.cc b/net/disk_cache/blockfile/entry_impl.cc
index ccfe4aa..01859bad 100644
--- a/net/disk_cache/blockfile/entry_impl.cc
+++ b/net/disk_cache/blockfile/entry_impl.cc
@@ -104,8 +104,7 @@
 // total memory used under control.
 class EntryImpl::UserBuffer {
  public:
-  explicit UserBuffer(BackendImpl* backend)
-      : backend_(backend->GetWeakPtr()), offset_(0), grow_allowed_(true) {
+  explicit UserBuffer(BackendImpl* backend) : backend_(backend->GetWeakPtr()) {
     buffer_.reserve(kMaxBlockSize);
   }
 
@@ -148,9 +147,9 @@
   bool GrowBuffer(int required, int limit);
 
   base::WeakPtr<BackendImpl> backend_;
-  int offset_;
+  int offset_ = 0;
   std::vector<char> buffer_;
-  bool grow_allowed_;
+  bool grow_allowed_ = true;
 };
 
 bool EntryImpl::UserBuffer::PreWrite(int offset, int len) {
@@ -318,9 +317,7 @@
     : entry_(nullptr, Addr(0)),
       node_(nullptr, Addr(0)),
       backend_(backend->GetWeakPtr()),
-      doomed_(false),
-      read_only_(read_only),
-      dirty_(false) {
+      read_only_(read_only) {
   entry_.LazyInit(backend->File(address), address);
   for (int i = 0; i < kNumStreams; i++) {
     unreported_size_[i] = 0;
diff --git a/net/disk_cache/blockfile/entry_impl.h b/net/disk_cache/blockfile/entry_impl.h
index aee2aac7..b758719 100644
--- a/net/disk_cache/blockfile/entry_impl.h
+++ b/net/disk_cache/blockfile/entry_impl.h
@@ -305,9 +305,9 @@
   scoped_refptr<File> files_[kNumStreams + 1];
   mutable std::string key_;           // Copy of the key.
   int unreported_size_[kNumStreams];  // Bytes not reported yet to the backend.
-  bool doomed_;               // True if this entry was removed from the cache.
+  bool doomed_ = false;       // True if this entry was removed from the cache.
   bool read_only_;            // True if not yet writing.
-  bool dirty_;                // True if we detected that this is a dirty entry.
+  bool dirty_ = false;        // True if we detected that this is a dirty entry.
   std::unique_ptr<SparseControl> sparse_;  // Support for sparse entries.
 };
 
diff --git a/net/disk_cache/blockfile/eviction.cc b/net/disk_cache/blockfile/eviction.cc
index 9061488e..e3236dc 100644
--- a/net/disk_cache/blockfile/eviction.cc
+++ b/net/disk_cache/blockfile/eviction.cc
@@ -79,7 +79,7 @@
 
 // The real initialization happens during Init(), init_ is the only member that
 // has to be initialized here.
-Eviction::Eviction() : backend_(nullptr), init_(false) {}
+Eviction::Eviction() : backend_(nullptr) {}
 
 Eviction::~Eviction() = default;
 
diff --git a/net/disk_cache/blockfile/eviction.h b/net/disk_cache/blockfile/eviction.h
index a33b5919..92e60c6 100644
--- a/net/disk_cache/blockfile/eviction.h
+++ b/net/disk_cache/blockfile/eviction.h
@@ -83,7 +83,7 @@
   bool first_trim_;
   bool trimming_;
   bool delay_trim_;
-  bool init_;
+  bool init_ = false;
   bool test_mode_;
   base::WeakPtrFactory<Eviction> ptr_factory_{this};
 };
diff --git a/net/disk_cache/blockfile/in_flight_io.cc b/net/disk_cache/blockfile/in_flight_io.cc
index a894e285..6d4d742e 100644
--- a/net/disk_cache/blockfile/in_flight_io.cc
+++ b/net/disk_cache/blockfile/in_flight_io.cc
@@ -15,8 +15,7 @@
 namespace disk_cache {
 
 BackgroundIO::BackgroundIO(InFlightIO* controller)
-    : result_(-1),
-      io_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
+    : io_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
                     base::WaitableEvent::InitialState::NOT_SIGNALED),
       controller_(controller) {}
 
@@ -38,8 +37,7 @@
 // ---------------------------------------------------------------------------
 
 InFlightIO::InFlightIO()
-    : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()),
-      running_(false) {}
+    : callback_task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
 InFlightIO::~InFlightIO() = default;
 
diff --git a/net/disk_cache/blockfile/in_flight_io.h b/net/disk_cache/blockfile/in_flight_io.h
index 76bdea5d..320775a3 100644
--- a/net/disk_cache/blockfile/in_flight_io.h
+++ b/net/disk_cache/blockfile/in_flight_io.h
@@ -61,7 +61,7 @@
   // thread.
   void NotifyController();
 
-  int result_;  // Final operation result.
+  int result_ = -1;  // Final operation result.
 
  private:
   friend class base::RefCountedThreadSafe<BackgroundIO>;
@@ -137,7 +137,7 @@
   IOList io_list_;  // List of pending, in-flight io operations.
   scoped_refptr<base::SequencedTaskRunner> callback_task_runner_;
 
-  bool running_;  // True after the first posted operation completes.
+  bool running_ = false;  // True after the first posted operation completes.
 #if DCHECK_IS_ON()
   bool single_thread_ = false;  // True if we only have one thread.
 #endif
diff --git a/net/disk_cache/blockfile/mapped_file.h b/net/disk_cache/blockfile/mapped_file.h
index 1291843..d5fb298 100644
--- a/net/disk_cache/blockfile/mapped_file.h
+++ b/net/disk_cache/blockfile/mapped_file.h
@@ -28,7 +28,7 @@
 // time).
 class NET_EXPORT_PRIVATE MappedFile : public File {
  public:
-  MappedFile() : File(true), init_(false) {}
+  MappedFile() : File(true) {}
 
   MappedFile(const MappedFile&) = delete;
   MappedFile& operator=(const MappedFile&) = delete;
@@ -56,7 +56,7 @@
  private:
   ~MappedFile() override;
 
-  bool init_;
+  bool init_ = false;
 #if BUILDFLAG(IS_WIN)
   HANDLE section_;
 #endif
diff --git a/net/disk_cache/blockfile/rankings.cc b/net/disk_cache/blockfile/rankings.cc
index e2bc135..0b8a068 100644
--- a/net/disk_cache/blockfile/rankings.cc
+++ b/net/disk_cache/blockfile/rankings.cc
@@ -218,7 +218,7 @@
   memset(this, 0, sizeof(Iterator));
 }
 
-Rankings::Rankings() : init_(false) {}
+Rankings::Rankings() = default;
 
 Rankings::~Rankings() = default;
 
diff --git a/net/disk_cache/blockfile/rankings.h b/net/disk_cache/blockfile/rankings.h
index 6f5b79c3..e942120 100644
--- a/net/disk_cache/blockfile/rankings.h
+++ b/net/disk_cache/blockfile/rankings.h
@@ -206,7 +206,7 @@
   void IncrementCounter(List list);
   void DecrementCounter(List list);
 
-  bool init_;
+  bool init_ = false;
   bool count_lists_;
   Addr heads_[LAST_ELEMENT];
   Addr tails_[LAST_ELEMENT];
diff --git a/net/disk_cache/blockfile/sparse_control.cc b/net/disk_cache/blockfile/sparse_control.cc
index 56a5026..f797e63 100644
--- a/net/disk_cache/blockfile/sparse_control.cc
+++ b/net/disk_cache/blockfile/sparse_control.cc
@@ -68,7 +68,7 @@
       public disk_cache::FileIOCallback {
  public:
   ChildrenDeleter(disk_cache::BackendImpl* backend, const std::string& name)
-      : backend_(backend->GetWeakPtr()), name_(name), signature_(0) {}
+      : backend_(backend->GetWeakPtr()), name_(name) {}
 
   ChildrenDeleter(const ChildrenDeleter&) = delete;
   ChildrenDeleter& operator=(const ChildrenDeleter&) = delete;
@@ -89,7 +89,7 @@
   base::WeakPtr<disk_cache::BackendImpl> backend_;
   std::string name_;
   disk_cache::Bitmap children_map_;
-  int64_t signature_;
+  int64_t signature_ = 0;
   std::unique_ptr<char[]> buffer_;
 };
 
@@ -203,18 +203,7 @@
 SparseControl::SparseControl(EntryImpl* entry)
     : entry_(entry),
       child_(nullptr),
-      operation_(kNoOperation),
-      pending_(false),
-      finished_(false),
-      init_(false),
-      range_found_(false),
-      abort_(false),
-      child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32),
-      offset_(0),
-      buf_len_(0),
-      child_offset_(0),
-      child_len_(0),
-      result_(0) {
+      child_map_(child_data_.bitmap, kNumSparseBits, kNumSparseBits / 32) {
   memset(&sparse_header_, 0, sizeof(sparse_header_));
   memset(&child_data_, 0, sizeof(child_data_));
 }
diff --git a/net/disk_cache/blockfile/sparse_control.h b/net/disk_cache/blockfile/sparse_control.h
index 30cc6a3..1ddcb39 100644
--- a/net/disk_cache/blockfile/sparse_control.h
+++ b/net/disk_cache/blockfile/sparse_control.h
@@ -157,12 +157,12 @@
 
   raw_ptr<EntryImpl> entry_;        // The sparse entry.
   scoped_refptr<EntryImpl> child_;  // The current child entry.
-  SparseOperation operation_;
-  bool pending_;  // True if any child IO operation returned pending.
-  bool finished_;
-  bool init_;
-  bool range_found_;  // True if GetAvailableRange found something.
-  bool abort_;  // True if we should abort the current operation ASAP.
+  SparseOperation operation_ = kNoOperation;
+  bool pending_ = false;  // True if any child IO operation returned pending.
+  bool finished_ = false;
+  bool init_ = false;
+  bool range_found_ = false;  // True if GetAvailableRange found something.
+  bool abort_ = false;  // True if we should abort the current operation ASAP.
 
   SparseHeader sparse_header_;  // Data about the children of entry_.
   Bitmap children_map_;  // The actual bitmap of children.
@@ -171,12 +171,12 @@
 
   CompletionOnceCallback user_callback_;
   std::vector<CompletionOnceCallback> abort_callbacks_;
-  int64_t offset_;  // Current sparse offset.
+  int64_t offset_ = 0;  // Current sparse offset.
   scoped_refptr<net::DrainableIOBuffer> user_buf_;
-  int buf_len_;  // Bytes to read or write.
-  int child_offset_;  // Offset to use for the current child.
-  int child_len_;  // Bytes to read or write for this child.
-  int result_;
+  int buf_len_ = 0;       // Bytes to read or write.
+  int child_offset_ = 0;  // Offset to use for the current child.
+  int child_len_ = 0;     // Bytes to read or write for this child.
+  int result_ = 0;
 };
 
 }  // namespace disk_cache
diff --git a/net/disk_cache/blockfile/storage_block-inl.h b/net/disk_cache/blockfile/storage_block-inl.h
index d83cab2..bb1ba39 100644
--- a/net/disk_cache/blockfile/storage_block-inl.h
+++ b/net/disk_cache/blockfile/storage_block-inl.h
@@ -18,12 +18,7 @@
 
 template <typename T>
 StorageBlock<T>::StorageBlock(MappedFile* file, Addr address)
-    : data_(nullptr),
-      file_(file),
-      address_(address),
-      modified_(false),
-      own_data_(false),
-      extended_(false) {
+    : data_(nullptr), file_(file), address_(address) {
   if (address.num_blocks() > 1)
     extended_ = true;
   DCHECK(!address.is_initialized() || sizeof(*data_) == address.BlockSize())
diff --git a/net/disk_cache/blockfile/storage_block.h b/net/disk_cache/blockfile/storage_block.h
index 3166e3b..e1e3acf 100644
--- a/net/disk_cache/blockfile/storage_block.h
+++ b/net/disk_cache/blockfile/storage_block.h
@@ -97,9 +97,10 @@
   raw_ptr<T> data_;
   raw_ptr<MappedFile> file_;
   Addr address_;
-  bool modified_;
-  bool own_data_;  // Is data_ owned by this object or shared with someone else.
-  bool extended_;  // Used to store an entry of more than one block.
+  bool modified_ = false;
+  bool own_data_ =
+      false;  // Is data_ owned by this object or shared with someone else.
+  bool extended_ = false;  // Used to store an entry of more than one block.
 };
 
 }  // namespace disk_cache
diff --git a/net/disk_cache/disk_cache.cc b/net/disk_cache/disk_cache.cc
index 771ea949..6f820bdd 100644
--- a/net/disk_cache/disk_cache.cc
+++ b/net/disk_cache/disk_cache.cc
@@ -70,7 +70,7 @@
 
   const base::FilePath path_;
   disk_cache::ResetHandling reset_handling_;
-  bool retry_;
+  bool retry_ = false;
   int64_t max_bytes_;
   net::CacheType type_;
   net::BackendType backend_type_;
@@ -104,7 +104,6 @@
     net::CompletionOnceCallback callback)
     : path_(path),
       reset_handling_(reset_handling),
-      retry_(false),
       max_bytes_(max_bytes),
       type_(type),
       backend_type_(backend_type),
diff --git a/net/disk_cache/disk_cache_test_base.cc b/net/disk_cache/disk_cache_test_base.cc
index cb30c80..9d18ab21 100644
--- a/net/disk_cache/disk_cache_test_base.cc
+++ b/net/disk_cache/disk_cache_test_base.cc
@@ -81,20 +81,7 @@
 }
 
 DiskCacheTestWithCache::DiskCacheTestWithCache()
-    : cache_impl_(nullptr),
-      simple_cache_impl_(nullptr),
-      mem_cache_(nullptr),
-      mask_(0),
-      size_(0),
-      type_(net::DISK_CACHE),
-      memory_only_(false),
-      simple_cache_mode_(false),
-      simple_cache_wait_for_index_(true),
-      force_creation_(false),
-      new_eviction_(false),
-      first_cleanup_(true),
-      integrity_(true),
-      use_current_thread_(false) {}
+    : cache_impl_(nullptr), simple_cache_impl_(nullptr), mem_cache_(nullptr) {}
 
 DiskCacheTestWithCache::~DiskCacheTestWithCache() = default;
 
diff --git a/net/disk_cache/disk_cache_test_base.h b/net/disk_cache/disk_cache_test_base.h
index 3060b05..1b8ec71c 100644
--- a/net/disk_cache/disk_cache_test_base.h
+++ b/net/disk_cache/disk_cache_test_base.h
@@ -202,17 +202,17 @@
   raw_ptr<disk_cache::SimpleBackendImpl> simple_cache_impl_;
   raw_ptr<disk_cache::MemBackendImpl> mem_cache_;
 
-  uint32_t mask_;
-  int64_t size_;
-  net::CacheType type_;
-  bool memory_only_;
-  bool simple_cache_mode_;
-  bool simple_cache_wait_for_index_;
-  bool force_creation_;
-  bool new_eviction_;
-  bool first_cleanup_;
-  bool integrity_;
-  bool use_current_thread_;
+  uint32_t mask_ = 0;
+  int64_t size_ = 0;
+  net::CacheType type_ = net::DISK_CACHE;
+  bool memory_only_ = false;
+  bool simple_cache_mode_ = false;
+  bool simple_cache_wait_for_index_ = true;
+  bool force_creation_ = false;
+  bool new_eviction_ = false;
+  bool first_cleanup_ = true;
+  bool integrity_ = true;
+  bool use_current_thread_ = false;
   // This is intentionally left uninitialized, to be used by any test.
   bool success_;
 
diff --git a/net/disk_cache/disk_cache_test_util.cc b/net/disk_cache/disk_cache_test_util.cc
index 6ae1262..ad1fb22 100644
--- a/net/disk_cache/disk_cache_test_util.cc
+++ b/net/disk_cache/disk_cache_test_util.cc
@@ -109,13 +109,7 @@
 
 // -----------------------------------------------------------------------
 
-MessageLoopHelper::MessageLoopHelper()
-    : num_callbacks_(0),
-      num_iterations_(0),
-      last_(0),
-      completed_(false),
-      callback_reused_error_(false),
-      callbacks_called_(0) {}
+MessageLoopHelper::MessageLoopHelper() = default;
 
 MessageLoopHelper::~MessageLoopHelper() = default;
 
diff --git a/net/disk_cache/disk_cache_test_util.h b/net/disk_cache/disk_cache_test_util.h
index 46ac0ac..c3586a1 100644
--- a/net/disk_cache/disk_cache_test_util.h
+++ b/net/disk_cache/disk_cache_test_util.h
@@ -129,14 +129,14 @@
   void TimerExpired();
 
   std::unique_ptr<base::RunLoop> run_loop_;
-  int num_callbacks_;
-  int num_iterations_;
-  int last_;
-  bool completed_;
+  int num_callbacks_ = 0;
+  int num_iterations_ = 0;
+  int last_ = 0;
+  bool completed_ = false;
 
   // True if a callback was called/reused more than expected.
-  bool callback_reused_error_;
-  int callbacks_called_;
+  bool callback_reused_error_ = false;
+  int callbacks_called_ = 0;
 };
 
 // -----------------------------------------------------------------------
diff --git a/net/disk_cache/memory/mem_backend_impl.cc b/net/disk_cache/memory/mem_backend_impl.cc
index 63d62769..f59f772 100644
--- a/net/disk_cache/memory/mem_backend_impl.cc
+++ b/net/disk_cache/memory/mem_backend_impl.cc
@@ -45,8 +45,6 @@
 MemBackendImpl::MemBackendImpl(net::NetLog* net_log)
     : Backend(net::MEMORY_CACHE),
       custom_clock_for_testing_(nullptr),
-      max_size_(0),
-      current_size_(0),
       net_log_(net_log),
       memory_pressure_listener_(
           FROM_HERE,
diff --git a/net/disk_cache/memory/mem_backend_impl.h b/net/disk_cache/memory/mem_backend_impl.h
index 396bba5..b0cebfb3 100644
--- a/net/disk_cache/memory/mem_backend_impl.h
+++ b/net/disk_cache/memory/mem_backend_impl.h
@@ -148,8 +148,8 @@
   // most recently used.
   base::LinkedList<MemEntryImpl> lru_list_;
 
-  int32_t max_size_;      // Maximum data size for this instance.
-  int32_t current_size_;
+  int32_t max_size_ = 0;  // Maximum data size for this instance.
+  int32_t current_size_ = 0;
 
   raw_ptr<net::NetLog> net_log_;
   base::OnceClosure post_cleanup_callback_;
diff --git a/net/disk_cache/simple/simple_backend_impl.cc b/net/disk_cache/simple/simple_backend_impl.cc
index 6b3b591..cec9824 100644
--- a/net/disk_cache/simple/simple_backend_impl.cc
+++ b/net/disk_cache/simple/simple_backend_impl.cc
@@ -86,15 +86,12 @@
 struct BarrierContext {
   explicit BarrierContext(net::CompletionOnceCallback final_callback,
                           int expected)
-      : final_callback_(std::move(final_callback)),
-        expected(expected),
-        count(0),
-        had_error(false) {}
+      : final_callback_(std::move(final_callback)), expected(expected) {}
 
   net::CompletionOnceCallback final_callback_;
   const int expected;
-  int count;
-  bool had_error;
+  int count = 0;
+  bool had_error = false;
 };
 
 void BarrierCompletionCallbackImpl(
diff --git a/net/disk_cache/simple/simple_file_tracker.cc b/net/disk_cache/simple/simple_file_tracker.cc
index 4b67514..45a78305 100644
--- a/net/disk_cache/simple/simple_file_tracker.cc
+++ b/net/disk_cache/simple/simple_file_tracker.cc
@@ -109,7 +109,7 @@
   }
 }
 
-SimpleFileTracker::TrackedFiles::TrackedFiles() : in_lru(false) {
+SimpleFileTracker::TrackedFiles::TrackedFiles() {
   std::fill(state, state + kSimpleEntryTotalFileCount, TF_NO_REGISTRATION);
 }
 
diff --git a/net/disk_cache/simple/simple_file_tracker.h b/net/disk_cache/simple/simple_file_tracker.h
index 2728e557..d9bf2d0 100644
--- a/net/disk_cache/simple/simple_file_tracker.h
+++ b/net/disk_cache/simple/simple_file_tracker.h
@@ -186,7 +186,7 @@
     // true if position_in_lru is valid. For entries where we closed everything,
     // we try not to keep them in the LRU so that we don't have to constantly
     // rescan them.
-    bool in_lru;
+    bool in_lru = false;
   };
 
   // Marks the file that was previously returned by Acquire as eligible for
diff --git a/net/disk_cache/simple/simple_index_file.cc b/net/disk_cache/simple/simple_index_file.cc
index 2d4ec8c2..c60d833 100644
--- a/net/disk_cache/simple/simple_index_file.cc
+++ b/net/disk_cache/simple/simple_index_file.cc
@@ -224,10 +224,7 @@
 
 }  // namespace
 
-SimpleIndexLoadResult::SimpleIndexLoadResult()
-    : did_load(false),
-      index_write_reason(SimpleIndex::INDEX_WRITE_REASON_MAX),
-      flush_required(false) {}
+SimpleIndexLoadResult::SimpleIndexLoadResult() = default;
 
 SimpleIndexLoadResult::~SimpleIndexLoadResult() = default;
 
diff --git a/net/disk_cache/simple/simple_index_file.h b/net/disk_cache/simple/simple_index_file.h
index b13435b8..53cda96 100644
--- a/net/disk_cache/simple/simple_index_file.h
+++ b/net/disk_cache/simple/simple_index_file.h
@@ -33,11 +33,12 @@
   ~SimpleIndexLoadResult();
   void Reset();
 
-  bool did_load;
+  bool did_load = false;
   SimpleIndex::EntrySet entries;
-  SimpleIndex::IndexWriteToDiskReason index_write_reason;
+  SimpleIndex::IndexWriteToDiskReason index_write_reason =
+      SimpleIndex::INDEX_WRITE_REASON_MAX;
   SimpleIndex::IndexInitMethod init_method;
-  bool flush_required;
+  bool flush_required = false;
 };
 
 // Simple Index File format is a pickle of IndexMetadata and EntryMetadata
diff --git a/net/disk_cache/simple/simple_synchronous_entry.cc b/net/disk_cache/simple/simple_synchronous_entry.cc
index 2f45685..4102a28b 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -116,9 +116,7 @@
 class SimpleSynchronousEntry::PrefetchData final {
  public:
   explicit PrefetchData(size_t file_size)
-      : file_size_(file_size),
-        offset_in_file_(0),
-        earliest_requested_offset_(file_size) {}
+      : file_size_(file_size), earliest_requested_offset_(file_size) {}
 
   // Returns true if the specified range within the file has been completely
   // prefetched.  Returns false if any part of the range has not been
@@ -186,7 +184,7 @@
   // Prefer to read the prefetch data into a stack buffer to minimize
   // memory pressure on the OS disk cache.
   base::StackVector<char, 1024> buffer_;
-  size_t offset_in_file_;
+  size_t offset_in_file_ = 0;
 
   size_t earliest_requested_offset_;
 };
@@ -299,10 +297,7 @@
 
 SimpleEntryCreationResults::SimpleEntryCreationResults(
     SimpleEntryStat entry_stat)
-    : sync_entry(nullptr),
-      entry_stat(entry_stat),
-      result(net::OK),
-      created(false) {}
+    : sync_entry(nullptr), entry_stat(entry_stat) {}
 
 SimpleEntryCreationResults::~SimpleEntryCreationResults() = default;
 
@@ -319,10 +314,7 @@
 SimpleSynchronousEntry::ReadRequest::ReadRequest(int index_p,
                                                  int offset_p,
                                                  int buf_len_p)
-    : index(index_p),
-      offset(offset_p),
-      buf_len(buf_len_p),
-      request_update_crc(false) {}
+    : index(index_p), offset(offset_p), buf_len(buf_len_p) {}
 
 SimpleSynchronousEntry::WriteRequest::WriteRequest(int index_p,
                                                    int offset_p,
diff --git a/net/disk_cache/simple/simple_synchronous_entry.h b/net/disk_cache/simple/simple_synchronous_entry.h
index 568df6d0..bf29e5e 100644
--- a/net/disk_cache/simple/simple_synchronous_entry.h
+++ b/net/disk_cache/simple/simple_synchronous_entry.h
@@ -23,6 +23,7 @@
 #include "base/strings/string_piece_forward.h"
 #include "base/time/time.h"
 #include "net/base/cache_type.h"
+#include "net/base/net_errors.h"
 #include "net/base/net_export.h"
 #include "net/disk_cache/simple/simple_entry_format.h"
 #include "net/disk_cache/simple/simple_file_tracker.h"
@@ -112,8 +113,8 @@
 
   SimpleEntryStat entry_stat;
   int32_t computed_trailer_prefetch_size = -1;
-  int result;
-  bool created;
+  int result = net::OK;
+  bool created = false;
 };
 
 struct SimpleEntryCloseResults {
@@ -144,15 +145,15 @@
     // Partial CRC of data immediately preceeding this read. Only relevant if
     // request_update_crc is set.
     uint32_t previous_crc32;
-    bool request_update_crc;
+    bool request_update_crc = false;
     bool request_verify_crc;  // only relevant if request_update_crc is set
   };
 
   struct ReadResult {
-    ReadResult() : crc_updated(false) {}
+    ReadResult() = default;
     int result;
     uint32_t updated_crc32;  // only relevant if crc_updated set
-    bool crc_updated;
+    bool crc_updated = false;
   };
 
   struct WriteRequest {
@@ -173,10 +174,10 @@
   };
 
   struct WriteResult {
-    WriteResult() : crc_updated(false) {}
+    WriteResult() = default;
     int result;
     uint32_t updated_crc32;  // only relevant if crc_updated set
-    bool crc_updated;
+    bool crc_updated = false;
   };
 
   struct SparseRequest {
diff --git a/net/dns/address_sorter_posix_unittest.cc b/net/dns/address_sorter_posix_unittest.cc
index 9a4a319..6bd613d 100644
--- a/net/dns/address_sorter_posix_unittest.cc
+++ b/net/dns/address_sorter_posix_unittest.cc
@@ -43,7 +43,7 @@
 class TestUDPClientSocket : public DatagramClientSocket {
  public:
   explicit TestUDPClientSocket(const AddressMapping* mapping)
-      : mapping_(mapping), connected_(false)  {}
+      : mapping_(mapping) {}
 
   TestUDPClientSocket(const TestUDPClientSocket&) = delete;
   TestUDPClientSocket& operator=(const TestUDPClientSocket&) = delete;
@@ -139,7 +139,7 @@
  private:
   NetLogWithSource net_log_;
   raw_ptr<const AddressMapping> mapping_;
-  bool connected_;
+  bool connected_ = false;
   IPEndPoint local_endpoint_;
 };
 
diff --git a/net/dns/dns_config_service.cc b/net/dns/dns_config_service.cc
index 1aafa73..d1df61f0 100644
--- a/net/dns/dns_config_service.cc
+++ b/net/dns/dns_config_service.cc
@@ -30,12 +30,7 @@
 DnsConfigService::DnsConfigService(
     base::FilePath::StringPieceType hosts_file_path,
     absl::optional<base::TimeDelta> config_change_delay)
-    : watch_failed_(false),
-      have_config_(false),
-      have_hosts_(false),
-      need_update_(false),
-      last_sent_empty_(true),
-      config_change_delay_(config_change_delay),
+    : config_change_delay_(config_change_delay),
       hosts_file_path_(hosts_file_path) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
diff --git a/net/dns/dns_config_service.h b/net/dns/dns_config_service.h
index bed76def..d4aa1802 100644
--- a/net/dns/dns_config_service.h
+++ b/net/dns/dns_config_service.h
@@ -205,15 +205,15 @@
 
   // True if any of the necessary watchers failed. In that case, the service
   // will communicate changes via OnTimeout, but will only send empty DnsConfig.
-  bool watch_failed_;
+  bool watch_failed_ = false;
   // True after On*Read, before Invalidate*. Tells if the config is complete.
-  bool have_config_;
-  bool have_hosts_;
+  bool have_config_ = false;
+  bool have_hosts_ = false;
   // True if receiver needs to be updated when the config becomes complete.
-  bool need_update_;
+  bool need_update_ = false;
   // True if the last config sent was empty (instead of |dns_config_|).
   // Set when |timer_| expires.
-  bool last_sent_empty_;
+  bool last_sent_empty_ = true;
 
   const absl::optional<base::TimeDelta> config_change_delay_;
   const base::FilePath hosts_file_path_;
diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc
index 06541a7..ab2cf0d 100644
--- a/net/dns/dns_hosts.cc
+++ b/net/dns/dns_hosts.cc
@@ -29,8 +29,6 @@
       : text_(text),
         data_(text.data()),
         end_(text.size()),
-        pos_(0),
-        token_is_ip_(false),
         comma_mode_(comma_mode) {}
 
   HostsParser(const HostsParser&) = delete;
@@ -127,9 +125,9 @@
   const char* data_;
   const size_t end_;
 
-  size_t pos_;
+  size_t pos_ = 0;
   StringPiece token_;
-  bool token_is_ip_;
+  bool token_is_ip_ = false;
 
   const ParseHostsCommaMode comma_mode_;
 };
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index 3a97987..8196946 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -200,7 +200,6 @@
                 std::unique_ptr<DnsQuery> query,
                 DnsUdpTracker* udp_tracker)
       : DnsAttempt(server_index),
-        next_state_(STATE_NONE),
         socket_(std::move(socket)),
         server_(server),
         query_(std::move(query)),
@@ -349,7 +348,7 @@
       std::move(callback_).Run(rv);
   }
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
   base::TimeTicks start_time_;
 
   std::unique_ptr<DatagramClientSocket> socket_;
@@ -649,12 +648,10 @@
                 std::unique_ptr<StreamSocket> socket,
                 std::unique_ptr<DnsQuery> query)
       : DnsAttempt(server_index),
-        next_state_(STATE_NONE),
         socket_(std::move(socket)),
         query_(std::move(query)),
         length_buffer_(
-            base::MakeRefCounted<IOBufferWithSize>(sizeof(uint16_t))),
-        response_length_(0) {}
+            base::MakeRefCounted<IOBufferWithSize>(sizeof(uint16_t))) {}
 
   DnsTCPAttempt(const DnsTCPAttempt&) = delete;
   DnsTCPAttempt& operator=(const DnsTCPAttempt&) = delete;
@@ -878,7 +875,7 @@
         base::BindOnce(&DnsTCPAttempt::OnIOComplete, base::Unretained(this)));
   }
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
   base::TimeTicks start_time_;
 
   std::unique_ptr<StreamSocket> socket_;
@@ -886,7 +883,7 @@
   scoped_refptr<IOBufferWithSize> length_buffer_;
   scoped_refptr<DrainableIOBuffer> buffer_;
 
-  uint16_t response_length_;
+  uint16_t response_length_ = 0;
   std::unique_ptr<DnsResponse> response_;
 
   CompletionOnceCallback callback_;
@@ -1118,11 +1115,7 @@
         secure_dns_mode_(secure_dns_mode),
         fast_timeout_(fast_timeout),
         net_log_(net_log),
-        qnames_initial_size_(0),
-        attempts_count_(0),
-        had_tcp_retry_(false),
-        resolve_context_(resolve_context->AsSafeRef()),
-        request_priority_(DEFAULT_PRIORITY) {
+        resolve_context_(resolve_context->AsSafeRef()) {
     DCHECK(session_.get());
     DCHECK(!hostname_.empty());
     DCHECK(!IsIPLiteral(hostname_));
@@ -1684,15 +1677,15 @@
 
   // Search list of fully-qualified DNS names to query next (in DNS format).
   base::circular_deque<std::string> qnames_;
-  size_t qnames_initial_size_;
+  size_t qnames_initial_size_ = 0;
 
   // List of attempts for the current name.
   std::vector<std::unique_ptr<DnsAttempt>> attempts_;
   // Count of attempts, not reset when |attempts_| vector is cleared.
-  int attempts_count_;
+  int attempts_count_ = 0;
 
   // Records when an attempt was retried via TCP due to a truncation error.
-  bool had_tcp_retry_;
+  bool had_tcp_retry_ = false;
 
   // Iterator to get the index of the DNS server for each search query.
   std::unique_ptr<DnsServerIterator> dns_server_iterator_;
@@ -1701,7 +1694,7 @@
   std::unique_ptr<base::ElapsedTimer> time_from_start_;
 
   base::SafeRef<ResolveContext> resolve_context_;
-  RequestPriority request_priority_;
+  RequestPriority request_priority_ = DEFAULT_PRIORITY;
 
   THREAD_CHECKER(thread_checker_);
 };
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 67d9ff6b..43ac7d35 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -443,8 +443,6 @@
       ResponseModifierCallback response_modifier = ResponseModifierCallback(),
       UrlRequestStartedCallback on_start = UrlRequestStartedCallback())
       : URLRequestJob(request),
-        content_length_(0),
-        leftover_data_len_(0),
         data_provider_(data_provider),
         response_modifier_(response_modifier),
         on_start_(on_start) {
@@ -585,9 +583,9 @@
     return data_len;
   }
 
-  const int content_length_;
+  const int content_length_ = 0;
   const char* leftover_data_;
-  int leftover_data_len_;
+  int leftover_data_len_ = 0;
   raw_ptr<SocketDataProvider> data_provider_;
   const ResponseModifierCallback response_modifier_;
   const UrlRequestStartedCallback on_start_;
@@ -2354,8 +2352,7 @@
 
 class CookieCallback {
  public:
-  CookieCallback()
-      : result_(false), loop_to_quit_(std::make_unique<base::RunLoop>()) {}
+  CookieCallback() : loop_to_quit_(std::make_unique<base::RunLoop>()) {}
 
   void SetCookieCallback(CookieAccessResult result) {
     result_ = result.status.IsInclude();
@@ -2380,7 +2377,7 @@
 
  private:
   net::CookieList list_;
-  bool result_;
+  bool result_ = false;
   std::unique_ptr<base::RunLoop> loop_to_quit_;
 };
 
@@ -2548,7 +2545,7 @@
 
 class CountingObserver : public net::NetLog::ThreadSafeObserver {
  public:
-  CountingObserver() : count_(0), dict_count_(0) {}
+  CountingObserver() = default;
 
   ~CountingObserver() override {
     if (net_log())
@@ -2566,8 +2563,8 @@
   int dict_count() const { return dict_count_; }
 
  private:
-  int count_;
-  int dict_count_;
+  int count_ = 0;
+  int dict_count_ = 0;
 };
 
 // Flaky on MSAN. https://crbug.com/1245953
diff --git a/net/dns/host_cache.cc b/net/dns/host_cache.cc
index dea347e..3c4ca83 100644
--- a/net/dns/host_cache.cc
+++ b/net/dns/host_cache.cc
@@ -630,8 +630,6 @@
 
 HostCache::HostCache(size_t max_entries)
     : max_entries_(max_entries),
-      network_changes_(0),
-      restore_size_(0),
       delegate_(nullptr),
       tick_clock_(base::DefaultTickClock::GetInstance()) {}
 
diff --git a/net/dns/host_cache.h b/net/dns/host_cache.h
index 07637c8..70d453ef 100644
--- a/net/dns/host_cache.h
+++ b/net/dns/host_cache.h
@@ -526,10 +526,10 @@
   // a resolved result entry.
   EntryMap entries_;
   size_t max_entries_;
-  int network_changes_;
+  int network_changes_ = 0;
   // Number of cache entries that were restored in the last call to
   // RestoreFromListValue(). Used in histograms.
-  size_t restore_size_;
+  size_t restore_size_ = 0;
 
   raw_ptr<PersistenceDelegate> delegate_;
   // Shared tick clock, overridden for testing.
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc
index 599b0c4..de7c47e 100644
--- a/net/dns/host_resolver_manager_unittest.cc
+++ b/net/dns/host_resolver_manager_unittest.cc
@@ -144,8 +144,6 @@
 
   MockHostResolverProc()
       : HostResolverProc(nullptr),
-        num_requests_waiting_(0),
-        num_slots_available_(0),
         requests_waiting_(&lock_),
         slots_available_(&lock_) {}
 
@@ -273,8 +271,8 @@
   mutable base::Lock lock_;
   std::map<ResolveKey, AddressList> rules_;
   CaptureList capture_list_;
-  unsigned num_requests_waiting_;
-  unsigned num_slots_available_;
+  unsigned num_requests_waiting_ = 0;
+  unsigned num_slots_available_ = 0;
   base::ConditionVariable requests_waiting_;
   base::ConditionVariable slots_available_;
 };
@@ -358,11 +356,7 @@
                                 int total_attempts)
       : HostResolverProc(previous),
         attempt_number_to_resolve_(attempt_number_to_resolve),
-        current_attempt_number_(0),
         total_attempts_(total_attempts),
-        total_attempts_resolved_(0),
-        resolved_attempt_number_(0),
-        num_attempts_waiting_(0),
         all_done_(&lock_),
         blocked_attempt_signal_(&lock_) {}
 
@@ -458,11 +452,11 @@
 
  private:
   int attempt_number_to_resolve_;
-  int current_attempt_number_;  // Incremented whenever Resolve is called.
+  int current_attempt_number_ = 0;  // Incremented whenever Resolve is called.
   int total_attempts_;
-  int total_attempts_resolved_;
-  int resolved_attempt_number_;
-  int num_attempts_waiting_;
+  int total_attempts_resolved_ = 0;
+  int resolved_attempt_number_ = 0;
+  int num_attempts_waiting_ = 0;
 
   // All attempts wait for right attempt to be resolve.
   base::Lock lock_;
diff --git a/net/dns/host_resolver_proc.cc b/net/dns/host_resolver_proc.cc
index a205f62..a98cbf2 100644
--- a/net/dns/host_resolver_proc.cc
+++ b/net/dns/host_resolver_proc.cc
@@ -258,8 +258,7 @@
                                size_t in_max_retry_attempts)
     : resolver_proc(resolver_proc),
       max_retry_attempts(in_max_retry_attempts),
-      unresponsive_delay(kDnsDefaultUnresponsiveDelay),
-      retry_factor(2) {
+      unresponsive_delay(kDnsDefaultUnresponsiveDelay) {
   // Maximum of 4 retry attempts for host resolution.
   static const size_t kDefaultMaxRetryAttempts = 4u;
   if (max_retry_attempts == HostResolver::ManagerOptions::kDefaultRetryAttempts)
diff --git a/net/dns/host_resolver_proc.h b/net/dns/host_resolver_proc.h
index cff9f64..2d7fd449 100644
--- a/net/dns/host_resolver_proc.h
+++ b/net/dns/host_resolver_proc.h
@@ -177,7 +177,7 @@
   base::TimeDelta unresponsive_delay;
 
   // Factor to grow |unresponsive_delay| when we re-re-try.
-  uint32_t retry_factor;
+  uint32_t retry_factor = 2;
 };
 
 }  // namespace net
diff --git a/net/dns/mdns_client_impl.cc b/net/dns/mdns_client_impl.cc
index 624912d6..2bd3b82 100644
--- a/net/dns/mdns_client_impl.cc
+++ b/net/dns/mdns_client_impl.cc
@@ -62,8 +62,7 @@
     MDnsConnection* connection)
     : socket_(std::move(socket)),
       connection_(connection),
-      response_(dns_protocol::kMaxMulticastSize),
-      send_in_progress_(false) {}
+      response_(dns_protocol::kMaxMulticastSize) {}
 
 MDnsConnection::SocketHandler::~SocketHandler() = default;
 
@@ -496,9 +495,7 @@
       name_(name),
       clock_(clock),
       client_(client),
-      delegate_(delegate),
-      started_(false),
-      active_refresh_(false) {}
+      delegate_(delegate) {}
 
 MDnsListenerImpl::~MDnsListenerImpl() {
   if (started_) {
@@ -628,7 +625,6 @@
       name_(name),
       callback_(callback),
       client_(client),
-      started_(false),
       flags_(flags) {
   DCHECK((flags_ & MDnsTransaction::FLAG_MASK) == flags_);
   DCHECK(flags_ & MDnsTransaction::QUERY_CACHE ||
diff --git a/net/dns/mdns_client_impl.h b/net/dns/mdns_client_impl.h
index 2bca834d..d21c1dbb 100644
--- a/net/dns/mdns_client_impl.h
+++ b/net/dns/mdns_client_impl.h
@@ -103,7 +103,7 @@
     IPEndPoint recv_addr_;
     DnsResponse response_;
     IPEndPoint multicast_addr_;
-    bool send_in_progress_;
+    bool send_in_progress_ = false;
     base::queue<std::pair<scoped_refptr<IOBuffer>, unsigned>> send_queue_;
   };
 
@@ -293,8 +293,8 @@
 
   base::Time last_update_;
   uint32_t ttl_;
-  bool started_;
-  bool active_refresh_;
+  bool started_ = false;
+  bool active_refresh_ = false;
 
   base::CancelableRepeatingClosure next_refresh_;
 };
@@ -360,7 +360,7 @@
 
   raw_ptr<MDnsClientImpl> client_;
 
-  bool started_;
+  bool started_ = false;
   int flags_;
 };
 
diff --git a/net/dns/mock_host_resolver.cc b/net/dns/mock_host_resolver.cc
index 6ac17d0a..6d33a9c 100644
--- a/net/dns/mock_host_resolver.cc
+++ b/net/dns/mock_host_resolver.cc
@@ -144,9 +144,7 @@
         priority_(parameters_.initial_priority),
         host_resolver_flags_(ParametersToHostResolverFlags(parameters_)),
         resolve_error_info_(ResolveErrorInfo(ERR_IO_PENDING)),
-        id_(0),
-        resolver_(resolver),
-        complete_(false) {}
+        resolver_(resolver) {}
 
   RequestImpl(const RequestImpl&) = delete;
   RequestImpl& operator=(const RequestImpl&) = delete;
@@ -382,13 +380,13 @@
   ResolveErrorInfo resolve_error_info_;
 
   // Used while stored with the resolver for async resolution.  Otherwise 0.
-  size_t id_;
+  size_t id_ = 0;
 
   CompletionOnceCallback callback_;
   // Use a WeakPtr as the resolver may be destroyed while there are still
   // outstanding request objects.
   base::WeakPtr<MockHostResolverBase> resolver_;
-  bool complete_;
+  bool complete_ = false;
 };
 
 class MockHostResolverBase::ProbeRequestImpl
@@ -882,11 +880,7 @@
 MockHostResolverBase::MockHostResolverBase(bool use_caching,
                                            int cache_invalidation_num,
                                            RuleResolver rule_resolver)
-    : last_request_priority_(DEFAULT_PRIORITY),
-      last_secure_dns_policy_(SecureDnsPolicy::kAllow),
-      synchronous_mode_(false),
-      ondemand_mode_(false),
-      rule_resolver_(std::move(rule_resolver)),
+    : rule_resolver_(std::move(rule_resolver)),
       initial_cache_invalidation_num_(cache_invalidation_num),
       tick_clock_(base::DefaultTickClock::GetInstance()),
       state_(base::MakeRefCounted<State>()) {
@@ -1147,8 +1141,7 @@
 
 RuleBasedHostResolverProc::RuleBasedHostResolverProc(HostResolverProc* previous,
                                                      bool allow_fallback)
-    : HostResolverProc(previous, allow_fallback),
-      modifications_allowed_(true) {}
+    : HostResolverProc(previous, allow_fallback) {}
 
 void RuleBasedHostResolverProc::AddRule(const std::string& host_pattern,
                                         const std::string& replacement) {
diff --git a/net/dns/mock_host_resolver.h b/net/dns/mock_host_resolver.h
index fb00c7b7..06f57b1 100644
--- a/net/dns/mock_host_resolver.h
+++ b/net/dns/mock_host_resolver.h
@@ -413,11 +413,11 @@
   void AddListener(MdnsListenerImpl* listener);
   void RemoveCancelledListener(MdnsListenerImpl* listener);
 
-  RequestPriority last_request_priority_;
+  RequestPriority last_request_priority_ = DEFAULT_PRIORITY;
   absl::optional<NetworkIsolationKey> last_request_network_isolation_key_;
-  SecureDnsPolicy last_secure_dns_policy_;
-  bool synchronous_mode_;
-  bool ondemand_mode_;
+  SecureDnsPolicy last_secure_dns_policy_ = SecureDnsPolicy::kAllow;
+  bool synchronous_mode_ = false;
+  bool ondemand_mode_ = false;
   RuleResolver rule_resolver_;
   std::unique_ptr<HostCache> cache_;
 
@@ -626,7 +626,7 @@
   base::Lock rule_lock_;
 
   // Whether changes are allowed.
-  bool modifications_allowed_;
+  bool modifications_allowed_ = true;
 };
 
 // Create rules that map all requests to localhost.
diff --git a/net/dns/record_rdata.cc b/net/dns/record_rdata.cc
index 26b46cb..8e969a1 100644
--- a/net/dns/record_rdata.cc
+++ b/net/dns/record_rdata.cc
@@ -54,8 +54,7 @@
   }
 }
 
-SrvRecordRdata::SrvRecordRdata() : priority_(0), weight_(0), port_(0) {
-}
+SrvRecordRdata::SrvRecordRdata() = default;
 
 SrvRecordRdata::~SrvRecordRdata() = default;
 
diff --git a/net/dns/record_rdata.h b/net/dns/record_rdata.h
index 8e4b4e6f..6097b96b 100644
--- a/net/dns/record_rdata.h
+++ b/net/dns/record_rdata.h
@@ -68,9 +68,9 @@
  private:
   SrvRecordRdata();
 
-  uint16_t priority_;
-  uint16_t weight_;
-  uint16_t port_;
+  uint16_t priority_ = 0;
+  uint16_t weight_ = 0;
+  uint16_t port_ = 0;
 
   std::string target_;
 };
diff --git a/net/dns/resolve_context.cc b/net/dns/resolve_context.cc
index 1eca1bc..52ffae34 100644
--- a/net/dns/resolve_context.cc
+++ b/net/dns/resolve_context.cc
@@ -119,7 +119,7 @@
 
 ResolveContext::ServerStats::ServerStats(
     std::unique_ptr<base::SampleVector> buckets)
-    : last_failure_count(0), rtt_histogram(std::move(buckets)) {}
+    : rtt_histogram(std::move(buckets)) {}
 
 ResolveContext::ServerStats::ServerStats(ServerStats&&) = default;
 
diff --git a/net/dns/resolve_context.h b/net/dns/resolve_context.h
index d9c0e756..f915332 100644
--- a/net/dns/resolve_context.h
+++ b/net/dns/resolve_context.h
@@ -206,7 +206,7 @@
     ~ServerStats();
 
     // Count of consecutive failures after last success.
-    int last_failure_count;
+    int last_failure_count = 0;
 
     // True if any success has ever been recorded for this server for the
     // current connection.
diff --git a/net/dns/serial_worker.cc b/net/dns/serial_worker.cc
index 5a3444b7f..ee0a6c3 100644
--- a/net/dns/serial_worker.cc
+++ b/net/dns/serial_worker.cc
@@ -49,8 +49,7 @@
 
 SerialWorker::SerialWorker(int max_number_of_retries,
                            const net::BackoffEntry::Policy* backoff_policy)
-    : state_(State::kIdle),
-      max_number_of_retries_(max_number_of_retries),
+    : max_number_of_retries_(max_number_of_retries),
       backoff_entry_(backoff_policy ? backoff_policy : &kDefaultBackoffPolicy) {
 }
 
diff --git a/net/dns/serial_worker.h b/net/dns/serial_worker.h
index b7076be..c226fe6 100644
--- a/net/dns/serial_worker.h
+++ b/net/dns/serial_worker.h
@@ -117,7 +117,7 @@
 
   void RerunWork(std::unique_ptr<WorkItem> work_item);
 
-  State state_;
+  State state_ = State::kIdle;
 
   // Max retries and backoff entry to control timing.
   const int max_number_of_retries_;
diff --git a/net/dns/serial_worker_unittest.cc b/net/dns/serial_worker_unittest.cc
index e04b0f1..d5e7e7f 100644
--- a/net/dns/serial_worker_unittest.cc
+++ b/net/dns/serial_worker_unittest.cc
@@ -168,8 +168,7 @@
         work_allowed_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                       base::WaitableEvent::InitialState::NOT_SIGNALED),
         work_called_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
-                     base::WaitableEvent::InitialState::NOT_SIGNALED),
-        work_running_(false) {}
+                     base::WaitableEvent::InitialState::NOT_SIGNALED) {}
 
   // Helpers for tests.
 
@@ -212,7 +211,7 @@
   base::WaitableEvent work_called_;
 
   // Protected by read_lock_. Used to verify that read calls are serialized.
-  bool work_running_;
+  bool work_running_ = false;
   base::Lock work_lock_;
 
   int work_finished_calls_ = 0;
diff --git a/net/extras/preload_data/decoder.cc b/net/extras/preload_data/decoder.cc
index 6fa8122..3db5c680 100644
--- a/net/extras/preload_data/decoder.cc
+++ b/net/extras/preload_data/decoder.cc
@@ -11,11 +11,7 @@
 namespace extras {
 
 PreloadDecoder::BitReader::BitReader(const uint8_t* bytes, size_t num_bits)
-    : bytes_(bytes),
-      num_bits_(num_bits),
-      num_bytes_((num_bits + 7) / 8),
-      current_byte_index_(0),
-      num_bits_used_(8) {}
+    : bytes_(bytes), num_bits_(num_bits), num_bytes_((num_bits + 7) / 8) {}
 
 // Next sets |*out| to the next bit from the input. It returns false if no
 // more bits are available or true otherwise.
diff --git a/net/extras/preload_data/decoder.h b/net/extras/preload_data/decoder.h
index 84fa144..b6076ac 100644
--- a/net/extras/preload_data/decoder.h
+++ b/net/extras/preload_data/decoder.h
@@ -79,12 +79,12 @@
     const size_t num_bits_;
     const size_t num_bytes_;
     // current_byte_index_ contains the current byte offset in |bytes_|.
-    size_t current_byte_index_;
+    size_t current_byte_index_ = 0;
     // current_byte_ contains the current byte of the input.
     uint8_t current_byte_;
     // num_bits_used_ contains the number of bits of |current_byte_| that have
     // been read.
-    unsigned num_bits_used_;
+    unsigned num_bits_used_ = 8;
   };
 
   // HuffmanDecoder is a very simple Huffman reader. The input Huffman tree is
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 058bae6e..945082c 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -263,10 +263,7 @@
                                          kCompatibleVersionNumber,
                                          std::move(background_task_runner),
                                          std::move(client_task_runner)),
-        num_pending_(0),
         restore_old_session_cookies_(restore_old_session_cookies),
-        num_priority_waiting_(0),
-        total_priority_requests_(0),
         crypto_(crypto_delegate) {}
 
   Backend(const Backend&) = delete;
@@ -401,7 +398,7 @@
   typedef std::map<CanonicalCookie::UniqueCookieKey, PendingOperationsForKey>
       PendingOperationsMap;
   PendingOperationsMap pending_ GUARDED_BY(lock_);
-  PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_);
+  PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_) = 0;
   // Guard |cookies_|, |pending_|, |num_pending_|.
   base::Lock lock_;
 
@@ -423,9 +420,9 @@
   // Guards the following metrics-related properties (only accessed when
   // starting/completing priority loads or completing the total load).
   base::Lock metrics_lock_;
-  int num_priority_waiting_ GUARDED_BY(metrics_lock_);
+  int num_priority_waiting_ GUARDED_BY(metrics_lock_) = 0;
   // The total number of priority requests.
-  int total_priority_requests_ GUARDED_BY(metrics_lock_);
+  int total_priority_requests_ GUARDED_BY(metrics_lock_) = 0;
   // The time when |num_priority_waiting_| incremented to 1.
   base::Time current_priority_wait_start_ GUARDED_BY(metrics_lock_);
   // The cumulative duration of time when |num_priority_waiting_| was greater
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
index e48be61..f4e67841 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_perftest.cc
@@ -58,8 +58,7 @@
 class SQLitePersistentCookieStorePerfTest : public testing::Test {
  public:
   SQLitePersistentCookieStorePerfTest()
-      : seed_multiple_(1),
-        test_start_(base::Time::Now()),
+      : test_start_(base::Time::Now()),
         loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                       base::WaitableEvent::InitialState::NOT_SIGNALED),
         key_loaded_event_(base::WaitableEvent::ResetPolicy::AUTOMATIC,
@@ -146,7 +145,7 @@
   }
 
  protected:
-  int seed_multiple_;
+  int seed_multiple_ = 1;
   base::Time test_start_;
   base::test::TaskEnvironment task_environment_;
   const scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
diff --git a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index bfe43d4d..6d6e470 100644
--- a/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -65,7 +65,7 @@
   bool DecryptString(const std::string& ciphertext,
                      std::string* plaintext) override;
 
-  bool should_encrypt_;
+  bool should_encrypt_ = true;
 
  private:
   std::unique_ptr<crypto::SymmetricKey> key_;
@@ -73,8 +73,7 @@
 };
 
 CookieCryptor::CookieCryptor()
-    : should_encrypt_(true),
-      key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
+    : key_(crypto::SymmetricKey::DeriveKeyFromPasswordUsingPbkdf2(
           crypto::SymmetricKey::AES,
           "password",
           "saltiest",
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc
index 21fca6e..e1fa9d9 100644
--- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc
+++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc
@@ -144,8 +144,7 @@
             kCurrentVersionNumber,
             kCompatibleVersionNumber,
             background_task_runner,
-            client_task_runner),
-        num_pending_(0) {}
+            client_task_runner) {}
 
   Backend(const Backend&) = delete;
   Backend& operator=(const Backend&) = delete;
@@ -302,7 +301,7 @@
 
   // Total number of pending operations (may not match the sum of the number of
   // elements in the pending operations queues, due to operation coalescing).
-  size_t num_pending_ GUARDED_BY(lock_);
+  size_t num_pending_ GUARDED_BY(lock_) = 0;
 
   // Queue of pending operations pertaining to NEL policies, keyed on origin.
   QueueType<NetworkErrorLoggingService::NelPolicyKey, NelPolicyInfo>
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
index 283d1a14..f7cc3a2 100644
--- a/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
+++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
@@ -28,8 +28,6 @@
     scoped_refptr<base::SequencedTaskRunner> client_task_runner)
     : path_(path),
       histogram_tag_(std::move(histogram_tag)),
-      initialized_(false),
-      corruption_detected_(false),
       current_version_number_(current_version_number),
       compatible_version_number_(compatible_version_number),
       background_task_runner_(std::move(background_task_runner)),
diff --git a/net/extras/sqlite/sqlite_persistent_store_backend_base.h b/net/extras/sqlite/sqlite_persistent_store_backend_base.h
index 09c8374..9f391f2 100644
--- a/net/extras/sqlite/sqlite_persistent_store_backend_base.h
+++ b/net/extras/sqlite/sqlite_persistent_store_backend_base.h
@@ -174,10 +174,10 @@
   const std::string histogram_tag_;
 
   // Whether the database has been initialized.
-  bool initialized_;
+  bool initialized_ = false;
 
   // Whether the KillDatabase callback has been scheduled.
-  bool corruption_detected_;
+  bool corruption_detected_ = false;
 
   // Current version number of the database. Must be greater than 0.
   const int current_version_number_;
diff --git a/net/filter/brotli_source_stream.cc b/net/filter/brotli_source_stream.cc
index 8adf3bf..5e708779 100644
--- a/net/filter/brotli_source_stream.cc
+++ b/net/filter/brotli_source_stream.cc
@@ -23,12 +23,7 @@
 class BrotliSourceStream : public FilterSourceStream {
  public:
   explicit BrotliSourceStream(std::unique_ptr<SourceStream> upstream)
-      : FilterSourceStream(SourceStream::TYPE_BROTLI, std::move(upstream)),
-        decoding_status_(DecodingStatus::DECODING_IN_PROGRESS),
-        used_memory_(0),
-        used_memory_maximum_(0),
-        consumed_bytes_(0),
-        produced_bytes_(0) {
+      : FilterSourceStream(SourceStream::TYPE_BROTLI, std::move(upstream)) {
     brotli_state_ =
         BrotliDecoderCreateInstance(AllocateMemory, FreeMemory, this);
     CHECK(brotli_state_);
@@ -169,12 +164,12 @@
 
   raw_ptr<BrotliDecoderState> brotli_state_;
 
-  DecodingStatus decoding_status_;
+  DecodingStatus decoding_status_ = DecodingStatus::DECODING_IN_PROGRESS;
 
-  size_t used_memory_;
-  size_t used_memory_maximum_;
-  size_t consumed_bytes_;
-  size_t produced_bytes_;
+  size_t used_memory_ = 0;
+  size_t used_memory_maximum_ = 0;
+  size_t consumed_bytes_ = 0;
+  size_t produced_bytes_ = 0;
 };
 
 }  // namespace
diff --git a/net/filter/filter_source_stream.cc b/net/filter/filter_source_stream.cc
index 6691053f..f3b00880 100644
--- a/net/filter/filter_source_stream.cc
+++ b/net/filter/filter_source_stream.cc
@@ -30,11 +30,7 @@
 
 FilterSourceStream::FilterSourceStream(SourceType type,
                                        std::unique_ptr<SourceStream> upstream)
-    : SourceStream(type),
-      upstream_(std::move(upstream)),
-      next_state_(STATE_NONE),
-      output_buffer_size_(0),
-      upstream_end_reached_(false) {
+    : SourceStream(type), upstream_(std::move(upstream)) {
   DCHECK(upstream_);
 }
 
diff --git a/net/filter/filter_source_stream.h b/net/filter/filter_source_stream.h
index a62509e..6450a55f 100644
--- a/net/filter/filter_source_stream.h
+++ b/net/filter/filter_source_stream.h
@@ -97,7 +97,7 @@
   // |upstream_| to |this_|.
   std::unique_ptr<SourceStream> upstream_;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   // Buffer for reading data out of |upstream_| and then for use by |this|
   // before the filtered data is returned through Read().
@@ -110,11 +110,11 @@
 
   // Not null if there is a pending Read.
   scoped_refptr<IOBuffer> output_buffer_;
-  int output_buffer_size_;
+  int output_buffer_size_ = 0;
   CompletionOnceCallback callback_;
 
   // Reading from |upstream_| has returned 0 byte or an error code.
-  bool upstream_end_reached_;
+  bool upstream_end_reached_ = false;
 };
 
 }  // namespace net
diff --git a/net/filter/filter_source_stream_unittest.cc b/net/filter/filter_source_stream_unittest.cc
index f21fc96..bba8fab 100644
--- a/net/filter/filter_source_stream_unittest.cc
+++ b/net/filter/filter_source_stream_unittest.cc
@@ -177,8 +177,7 @@
   NoOutputSourceStream(std::unique_ptr<SourceStream> upstream,
                        size_t expected_input_size)
       : TestFilterSourceStreamBase(std::move(upstream)),
-        expected_input_size_(expected_input_size),
-        consumed_all_input_(false) {}
+        expected_input_size_(expected_input_size) {}
 
   NoOutputSourceStream(const NoOutputSourceStream&) = delete;
   NoOutputSourceStream& operator=(const NoOutputSourceStream&) = delete;
@@ -201,7 +200,7 @@
  private:
   // Expected remaining bytes to be received from |upstream|.
   int expected_input_size_;
-  bool consumed_all_input_;
+  bool consumed_all_input_ = false;
 };
 
 // A FilterSourceStream return an error code in FilterData().
diff --git a/net/filter/gzip_source_stream.cc b/net/filter/gzip_source_stream.cc
index 32b89e2..e68bd1a 100644
--- a/net/filter/gzip_source_stream.cc
+++ b/net/filter/gzip_source_stream.cc
@@ -53,10 +53,7 @@
 
 GzipSourceStream::GzipSourceStream(std::unique_ptr<SourceStream> upstream,
                                    SourceStream::SourceType type)
-    : FilterSourceStream(type, std::move(upstream)),
-      gzip_footer_bytes_left_(0),
-      input_state_(STATE_START),
-      replay_state_(STATE_COMPRESSED_BODY) {}
+    : FilterSourceStream(type, std::move(upstream)) {}
 
 bool GzipSourceStream::Init() {
   zlib_stream_ = std::make_unique<z_stream>();
diff --git a/net/filter/gzip_source_stream.h b/net/filter/gzip_source_stream.h
index 5774d0a..80633e4 100644
--- a/net/filter/gzip_source_stream.h
+++ b/net/filter/gzip_source_stream.h
@@ -102,13 +102,13 @@
   GZipHeader gzip_header_;
 
   // Tracks how many bytes of gzip footer are yet to be filtered.
-  size_t gzip_footer_bytes_left_;
+  size_t gzip_footer_bytes_left_ = 0;
 
   // Tracks the state of the input stream.
-  InputState input_state_;
+  InputState input_state_ = STATE_START;
 
   // Used when replaying data.
-  InputState replay_state_;
+  InputState replay_state_ = STATE_COMPRESSED_BODY;
 };
 
 }  // namespace net
diff --git a/net/log/file_net_log_observer.cc b/net/log/file_net_log_observer.cc
index bde6ccc..f92b834 100644
--- a/net/log/file_net_log_observer.cc
+++ b/net/log/file_net_log_observer.cc
@@ -173,7 +173,7 @@
   // runner's local queue is swapped with the shared write queue.
   //
   // |lock_| must be acquired to read or write to this.
-  uint64_t memory_;
+  uint64_t memory_ = 0;
 
   // Indicates the maximum amount of memory that the |queue_| is allowed to
   // use.
@@ -317,7 +317,7 @@
 
   // Counter for the events file currently being written into. See
   // FileNumberToIndex() for an explanation of what "number" vs "index" mean.
-  size_t current_event_file_number_;
+  size_t current_event_file_number_ = 0;
 
   // Indicates the maximum size of each individual events file. May be kNoLimit
   // to indicate that it can grow arbitrarily large.
@@ -325,7 +325,7 @@
 
   // Whether any bytes were written for events. This is used to properly format
   // JSON (events list shouldn't end with a comma).
-  bool wrote_event_bytes_;
+  bool wrote_event_bytes_ = false;
 
   // Task runner for doing file operations.
   const scoped_refptr<base::SequencedTaskRunner> task_runner_;
@@ -516,7 +516,7 @@
 }
 
 FileNetLogObserver::WriteQueue::WriteQueue(uint64_t memory_max)
-    : memory_(0), memory_max_(memory_max) {}
+    : memory_max_(memory_max) {}
 
 size_t FileNetLogObserver::WriteQueue::AddEntryToQueue(
     std::unique_ptr<std::string> event) {
@@ -554,9 +554,7 @@
     : final_log_path_(log_path),
       inprogress_dir_path_(inprogress_dir_path),
       total_num_event_files_(total_num_event_files),
-      current_event_file_number_(0),
       max_event_file_size_(max_event_file_size),
-      wrote_event_bytes_(false),
       task_runner_(std::move(task_runner)) {
   DCHECK_EQ(pre_existing_log_file.has_value(), log_path.empty());
   DCHECK_EQ(IsBounded(), !inprogress_dir_path.empty());
diff --git a/net/log/net_log.cc b/net/log/net_log.cc
index dd76223..2bb696e 100644
--- a/net/log/net_log.cc
+++ b/net/log/net_log.cc
@@ -14,8 +14,7 @@
 
 namespace net {
 
-NetLog::ThreadSafeObserver::ThreadSafeObserver()
-    : capture_mode_(NetLogCaptureMode::kDefault), net_log_(nullptr) {}
+NetLog::ThreadSafeObserver::ThreadSafeObserver() : net_log_(nullptr) {}
 
 NetLog::ThreadSafeObserver::~ThreadSafeObserver() {
   // Make sure we aren't watching a NetLog on destruction.  Because the NetLog
diff --git a/net/log/net_log.h b/net/log/net_log.h
index 9a6fc19..a89dbc56 100644
--- a/net/log/net_log.h
+++ b/net/log/net_log.h
@@ -136,7 +136,7 @@
     friend class NetLog;
 
     // Both of these values are only modified by the NetLog.
-    NetLogCaptureMode capture_mode_;
+    NetLogCaptureMode capture_mode_ = NetLogCaptureMode::kDefault;
     raw_ptr<NetLog> net_log_;
   };
 
diff --git a/net/log/net_log_unittest.cc b/net/log/net_log_unittest.cc
index 7ef0ca73..b0de08e 100644
--- a/net/log/net_log_unittest.cc
+++ b/net/log/net_log_unittest.cc
@@ -186,7 +186,7 @@
 
 class CountingObserver : public NetLog::ThreadSafeObserver {
  public:
-  CountingObserver() : count_(0) {}
+  CountingObserver() = default;
 
   ~CountingObserver() override {
     if (net_log())
@@ -198,7 +198,7 @@
   int count() const { return count_; }
 
  private:
-  int count_;
+  int count_ = 0;
 };
 
 class LoggingObserver : public NetLog::ThreadSafeObserver {
diff --git a/net/network_error_logging/mock_persistent_nel_store.cc b/net/network_error_logging/mock_persistent_nel_store.cc
index 468c241..1d252d5 100644
--- a/net/network_error_logging/mock_persistent_nel_store.cc
+++ b/net/network_error_logging/mock_persistent_nel_store.cc
@@ -50,8 +50,7 @@
   return !(lhs == rhs);
 }
 
-MockPersistentNelStore::MockPersistentNelStore()
-    : load_started_(false), policy_count_(0), queued_policy_count_delta_(0) {}
+MockPersistentNelStore::MockPersistentNelStore() = default;
 
 MockPersistentNelStore::~MockPersistentNelStore() = default;
 
diff --git a/net/network_error_logging/mock_persistent_nel_store.h b/net/network_error_logging/mock_persistent_nel_store.h
index 0843586..7dc9835 100644
--- a/net/network_error_logging/mock_persistent_nel_store.h
+++ b/net/network_error_logging/mock_persistent_nel_store.h
@@ -104,15 +104,15 @@
   std::vector<NetworkErrorLoggingService::NelPolicy> prestored_policies_;
 
   // Set when LoadNelPolicies() is called.
-  bool load_started_;
+  bool load_started_ = false;
 
   // Simulates the total number of policies that would be stored in the store.
   // Updated when pre-stored policies are added, and when Flush() is called.
-  int policy_count_;
+  int policy_count_ = 0;
 
   // Simulates the delta to be added to |policy_count_| the next time Flush() is
   // called. Reset to 0 when Flush() is called.
-  int queued_policy_count_delta_;
+  int queued_policy_count_delta_ = 0;
 };
 
 bool operator==(const MockPersistentNelStore::Command& lhs,
diff --git a/net/network_error_logging/network_error_logging_service.cc b/net/network_error_logging/network_error_logging_service.cc
index 092b70f..37b4dee 100644
--- a/net/network_error_logging/network_error_logging_service.cc
+++ b/net/network_error_logging/network_error_logging_service.cc
@@ -155,7 +155,7 @@
 class NetworkErrorLoggingServiceImpl : public NetworkErrorLoggingService {
  public:
   explicit NetworkErrorLoggingServiceImpl(PersistentNelStore* store)
-      : store_(store), started_loading_policies_(false), initialized_(false) {
+      : store_(store) {
     if (!PoliciesArePersisted())
       initialized_ = true;
   }
@@ -319,7 +319,7 @@
 
   // Set to true when we have told the store to load NEL policies. This is to
   // make sure we don't try to load policies multiple times.
-  bool started_loading_policies_;
+  bool started_loading_policies_ = false;
 
   // Set to true when the NEL service has been initialized. Before
   // initialization is complete, commands to the NEL service (i.e. public
@@ -328,7 +328,7 @@
   // there is no PersistentNelStore. If there is a store, then initialization is
   // complete when the NEL policies have finished being loaded from the store
   // (either successfully or unsuccessfully).
-  bool initialized_;
+  bool initialized_ = false;
 
   // Backlog of tasks waiting on initialization.
   std::vector<base::OnceClosure> task_backlog_;
@@ -1043,8 +1043,6 @@
 }
 
 NetworkErrorLoggingService::NetworkErrorLoggingService()
-    : clock_(base::DefaultClock::GetInstance()),
-      reporting_service_(nullptr),
-      shut_down_(false) {}
+    : clock_(base::DefaultClock::GetInstance()), reporting_service_(nullptr) {}
 
 }  // namespace net
diff --git a/net/network_error_logging/network_error_logging_service.h b/net/network_error_logging/network_error_logging_service.h
index ad226da..fa56764 100644
--- a/net/network_error_logging/network_error_logging_service.h
+++ b/net/network_error_logging/network_error_logging_service.h
@@ -293,7 +293,7 @@
   // Unowned:
   raw_ptr<const base::Clock> clock_;
   raw_ptr<ReportingService> reporting_service_;
-  bool shut_down_;
+  bool shut_down_ = false;
 };
 
 // Persistent storage for NEL policies.
diff --git a/net/nqe/event_creator.cc b/net/nqe/event_creator.cc
index 341d4059..f415567 100644
--- a/net/nqe/event_creator.cc
+++ b/net/nqe/event_creator.cc
@@ -72,9 +72,7 @@
 
 }  // namespace
 
-EventCreator::EventCreator(NetLogWithSource net_log)
-    : net_log_(net_log),
-      past_effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {}
+EventCreator::EventCreator(NetLogWithSource net_log) : net_log_(net_log) {}
 
 EventCreator::~EventCreator() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/net/nqe/event_creator.h b/net/nqe/event_creator.h
index a63aa7b..7a614cb 100644
--- a/net/nqe/event_creator.h
+++ b/net/nqe/event_creator.h
@@ -44,7 +44,8 @@
   NetLogWithSource net_log_;
 
   // The effective connection type when the net log event was last added.
-  EffectiveConnectionType past_effective_connection_type_;
+  EffectiveConnectionType past_effective_connection_type_ =
+      EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
 
   //  The network quality when the net log event was last added.
   NetworkQuality past_network_quality_;
diff --git a/net/nqe/network_qualities_prefs_manager_unittest.cc b/net/nqe/network_qualities_prefs_manager_unittest.cc
index f3b78412..d1e484da 100644
--- a/net/nqe/network_qualities_prefs_manager_unittest.cc
+++ b/net/nqe/network_qualities_prefs_manager_unittest.cc
@@ -27,7 +27,7 @@
 
 class TestPrefDelegate : public NetworkQualitiesPrefsManager::PrefDelegate {
  public:
-  TestPrefDelegate() : write_count_(0), read_count_(0) {}
+  TestPrefDelegate() = default;
 
   TestPrefDelegate(const TestPrefDelegate&) = delete;
   TestPrefDelegate& operator=(const TestPrefDelegate&) = delete;
@@ -63,8 +63,8 @@
 
  private:
   // Number of times prefs were written and read, respectively..
-  size_t write_count_;
-  size_t read_count_;
+  size_t write_count_ = 0;
+  size_t read_count_ = 0;
 
   // Current value of the prefs.
   base::Value::Dict value_;
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index f5f02357..376fccd 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -93,9 +93,6 @@
     std::unique_ptr<NetworkQualityEstimatorParams> params,
     NetLog* net_log)
     : params_(std::move(params)),
-      end_to_end_rtt_observation_count_at_last_ect_computation_(0),
-      use_localhost_requests_(false),
-      disable_offline_check_(false),
       tick_clock_(base::DefaultTickClock::GetInstance()),
       last_connection_change_(tick_clock_->NowTicks()),
       current_network_id_(nqe::internal::NetworkID(
@@ -123,16 +120,7 @@
               tick_clock_,
               params_->weight_multiplier_per_second(),
               1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)},
-      effective_connection_type_at_last_main_frame_(
-          EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
       effective_connection_type_recomputation_interval_(base::Seconds(10)),
-      rtt_observations_size_at_last_ect_computation_(0),
-      throughput_observations_size_at_last_ect_computation_(0),
-      transport_rtt_observation_count_last_ect_computation_(0),
-      new_rtt_observations_since_last_ect_computation_(0),
-      new_throughput_observations_since_last_ect_computation_(0),
-      effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
-      cached_estimate_applied_(false),
       net_log_(NetLogWithSource::Make(
           net_log,
           net::NetLogSourceType::NETWORK_QUALITY_ESTIMATOR)),
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h
index 1f1fa80..d0f263c 100644
--- a/net/nqe/network_quality_estimator.h
+++ b/net/nqe/network_quality_estimator.h
@@ -414,7 +414,7 @@
   const std::unique_ptr<NetworkQualityEstimatorParams> params_;
 
   // Number of end to end RTT samples available when the ECT was last computed.
-  size_t end_to_end_rtt_observation_count_at_last_ect_computation_;
+  size_t end_to_end_rtt_observation_count_at_last_ect_computation_ = 0;
 
   // Current count of active peer to peer connections.
   uint32_t p2p_connections_count_ = 0u;
@@ -542,12 +542,12 @@
 
   // Determines if the requests to local host can be used in estimating the
   // network quality. Set to true only for tests.
-  bool use_localhost_requests_;
+  bool use_localhost_requests_ = false;
 
   // When set to true, the device offline check is disabled when computing the
   // effective connection type or when writing the prefs. Set to true only for
   // testing.
-  bool disable_offline_check_;
+  bool disable_offline_check_ = false;
 
   // Tick clock used by the network quality estimator.
   raw_ptr<const base::TickClock> tick_clock_;
@@ -576,7 +576,8 @@
   // Estimated network quality when the transaction for the last main frame
   // request was started.
   nqe::internal::NetworkQuality estimated_quality_at_last_main_frame_;
-  EffectiveConnectionType effective_connection_type_at_last_main_frame_;
+  EffectiveConnectionType effective_connection_type_at_last_main_frame_ =
+      EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
 
   // Observer lists for round trip times and throughput measurements.
   base::ObserverList<RTTObserver>::Unchecked rtt_observer_list_;
@@ -599,19 +600,19 @@
 
   // Number of RTT and bandwidth samples available when effective connection
   // type was last recomputed.
-  size_t rtt_observations_size_at_last_ect_computation_;
-  size_t throughput_observations_size_at_last_ect_computation_;
+  size_t rtt_observations_size_at_last_ect_computation_ = 0;
+  size_t throughput_observations_size_at_last_ect_computation_ = 0;
 
   // Number of transport RTT samples available when the ECT was last computed.
-  size_t transport_rtt_observation_count_last_ect_computation_;
+  size_t transport_rtt_observation_count_last_ect_computation_ = 0;
 
   // Number of RTT observations received since the effective connection type was
   // last computed.
-  size_t new_rtt_observations_since_last_ect_computation_;
+  size_t new_rtt_observations_since_last_ect_computation_ = 0;
 
   // Number of throughput observations received since the effective connection
   // type was last computed.
-  size_t new_throughput_observations_since_last_ect_computation_;
+  size_t new_throughput_observations_since_last_ect_computation_ = 0;
 
   // Current estimate of the network quality.
   nqe::internal::NetworkQuality network_quality_;
@@ -621,14 +622,15 @@
   // events. It is also updated every time there is network traffic (provided
   // the last computation was more than
   // |effective_connection_type_recomputation_interval_| ago).
-  EffectiveConnectionType effective_connection_type_;
+  EffectiveConnectionType effective_connection_type_ =
+      EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
 
   // Stores the qualities of different networks.
   std::unique_ptr<nqe::internal::NetworkQualityStore> network_quality_store_;
 
   // True if a cached RTT or throughput estimate was available and the
   // corresponding observation has been added on the current network.
-  bool cached_estimate_applied_;
+  bool cached_estimate_applied_ = false;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc
index 5f8d556d..2cb3bfa 100644
--- a/net/nqe/network_quality_estimator_params.cc
+++ b/net/nqe/network_quality_estimator_params.cc
@@ -431,7 +431,6 @@
           GetPersistentCacheReadingEnabled(params_)),
       min_socket_watcher_notification_interval_(
           GetMinSocketWatcherNotificationInterval(params_)),
-      lower_bound_http_rtt_transport_rtt_multiplier_(1.0),
       upper_bound_http_rtt_endtoend_rtt_multiplier_(
           GetDoubleValueForVariationParamWithDefaultValue(
               params_,
@@ -482,19 +481,16 @@
               params_,
               "socket_watchers_min_notification_interval_msec",
               200))),
-      use_end_to_end_rtt_(true),
       upper_bound_typical_kbps_multiplier_(
           GetDoubleValueForVariationParamWithDefaultValue(
               params_,
               "upper_bound_typical_kbps_multiplier",
               3.5)),
-
       adjust_rtt_based_on_rtt_counts_(
           GetStringValueForVariationParamWithDefaultValue(
               params_,
               "adjust_rtt_based_on_rtt_counts",
-              "false") == "true"),
-      use_small_responses_(false) {
+              "false") == "true") {
   DCHECK(hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ == -1 ||
          hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ > 0);
   DCHECK(hanging_request_http_rtt_upper_bound_http_rtt_multiplier_ == -1 ||
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h
index 6872f51..3a34c0b 100644
--- a/net/nqe/network_quality_estimator_params.h
+++ b/net/nqe/network_quality_estimator_params.h
@@ -272,7 +272,7 @@
   const bool forced_effective_connection_type_on_cellular_only_;
   bool persistent_cache_reading_enabled_;
   const base::TimeDelta min_socket_watcher_notification_interval_;
-  const double lower_bound_http_rtt_transport_rtt_multiplier_;
+  const double lower_bound_http_rtt_transport_rtt_multiplier_ = 1.0;
   const double upper_bound_http_rtt_endtoend_rtt_multiplier_;
   const int hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_;
   const int hanging_request_http_rtt_upper_bound_http_rtt_multiplier_;
@@ -285,11 +285,11 @@
   const base::TimeDelta hanging_request_min_duration_;
   const bool add_default_platform_observations_;
   const base::TimeDelta socket_watchers_min_notification_interval_;
-  const bool use_end_to_end_rtt_;
+  const bool use_end_to_end_rtt_ = true;
   const double upper_bound_typical_kbps_multiplier_;
   const bool adjust_rtt_based_on_rtt_counts_;
 
-  bool use_small_responses_;
+  bool use_small_responses_ = false;
 
   // Default network quality observations obtained from |params_|.
   nqe::internal::NetworkQuality
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index 9613337..db6acb0a 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -113,9 +113,7 @@
  public:
   TestRTTAndThroughputEstimatesObserver()
       : http_rtt_(nqe::internal::InvalidRTT()),
-        transport_rtt_(nqe::internal::InvalidRTT()),
-        downstream_throughput_kbps_(nqe::internal::INVALID_RTT_THROUGHPUT),
-        notifications_received_(0) {}
+        transport_rtt_(nqe::internal::InvalidRTT()) {}
 
   // RTTAndThroughputEstimatesObserver implementation:
   void OnRTTOrThroughputEstimatesComputed(
@@ -139,8 +137,8 @@
  private:
   base::TimeDelta http_rtt_;
   base::TimeDelta transport_rtt_;
-  int32_t downstream_throughput_kbps_;
-  int notifications_received_;
+  int32_t downstream_throughput_kbps_ = nqe::internal::INVALID_RTT_THROUGHPUT;
+  int notifications_received_ = 0;
 };
 
 class TestRTTObserver : public NetworkQualityEstimator::RTTObserver {
@@ -2182,8 +2180,7 @@
   TestNetworkQualitiesCacheObserver()
       : network_id_(net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
                     std::string(),
-                    INT32_MIN),
-        notification_received_(0) {}
+                    INT32_MIN) {}
 
   TestNetworkQualitiesCacheObserver(const TestNetworkQualitiesCacheObserver&) =
       delete;
@@ -2210,7 +2207,7 @@
 
  private:
   nqe::internal::NetworkID network_id_;
-  size_t notification_received_;
+  size_t notification_received_ = 0;
 };
 
 TEST_F(NetworkQualityEstimatorTest, CacheObserver) {
diff --git a/net/nqe/socket_watcher.cc b/net/nqe/socket_watcher.cc
index 6ad5756..09404b7c 100644
--- a/net/nqe/socket_watcher.cc
+++ b/net/nqe/socket_watcher.cc
@@ -71,7 +71,6 @@
                         (!address_list.empty() &&
                          address_list.front().address().IsPubliclyRoutable())),
       tick_clock_(tick_clock),
-      first_quic_rtt_notification_received_(false),
       host_(CalculateIPHash(address_list)) {
   DCHECK(tick_clock_);
   DCHECK(last_rtt_notification_.is_null());
diff --git a/net/nqe/socket_watcher.h b/net/nqe/socket_watcher.h
index 9d20409..5d3ebda 100644
--- a/net/nqe/socket_watcher.h
+++ b/net/nqe/socket_watcher.h
@@ -106,7 +106,7 @@
 
   // True if the first RTT notification from the QUIC connection has been
   // received.
-  bool first_quic_rtt_notification_received_;
+  bool first_quic_rtt_notification_received_ = false;
 
   // A unique identifier for the remote host that this socket connects to.
   const absl::optional<IPHash> host_;
diff --git a/net/nqe/socket_watcher_factory.cc b/net/nqe/socket_watcher_factory.cc
index 884ea77..64b095a0 100644
--- a/net/nqe/socket_watcher_factory.cc
+++ b/net/nqe/socket_watcher_factory.cc
@@ -21,7 +21,6 @@
     const base::TickClock* tick_clock)
     : task_runner_(std::move(task_runner)),
       min_notification_interval_(min_notification_interval),
-      allow_rtt_private_address_(false),
       updated_rtt_observation_callback_(updated_rtt_observation_callback),
       should_notify_rtt_callback_(should_notify_rtt_callback),
       tick_clock_(tick_clock) {
diff --git a/net/nqe/socket_watcher_factory.h b/net/nqe/socket_watcher_factory.h
index 80fb3c6..d3d4598 100644
--- a/net/nqe/socket_watcher_factory.h
+++ b/net/nqe/socket_watcher_factory.h
@@ -87,7 +87,7 @@
 
   // True if socket watchers constructed by this factory can use the RTT from
   // the sockets that are connected to the private addresses.
-  bool allow_rtt_private_address_;
+  bool allow_rtt_private_address_ = false;
 
   // Called every time a new RTT observation is available.
   OnUpdatedRTTAvailableCallback updated_rtt_observation_callback_;
diff --git a/net/nqe/throughput_analyzer.cc b/net/nqe/throughput_analyzer.cc
index d83e6f0..08657ae4 100644
--- a/net/nqe/throughput_analyzer.cc
+++ b/net/nqe/throughput_analyzer.cc
@@ -59,10 +59,6 @@
       tick_clock_(tick_clock),
       last_connection_change_(tick_clock_->NowTicks()),
       window_start_time_(base::TimeTicks()),
-      bits_received_at_window_start_(0),
-      total_response_content_size_(0),
-      disable_throughput_measurements_(false),
-      use_localhost_requests_for_tests_(false),
       net_log_(net_log) {
   DCHECK(tick_clock_);
   DCHECK(network_quality_estimator_);
diff --git a/net/nqe/throughput_analyzer.h b/net/nqe/throughput_analyzer.h
index 784f0d11..51d4cd02 100644
--- a/net/nqe/throughput_analyzer.h
+++ b/net/nqe/throughput_analyzer.h
@@ -218,7 +218,7 @@
 
   // Number of bits received prior to |start_| as reported by
   // NetworkActivityMonitor.
-  int64_t bits_received_at_window_start_;
+  int64_t bits_received_at_window_start_ = 0;
 
   // Container that holds active requests that reduce the accuracy of
   // throughput computation. These requests are not used in throughput
@@ -234,7 +234,7 @@
   ResponseContentSizes response_content_sizes_;
 
   // The running total of response content size for all inflight requests.
-  int64_t total_response_content_size_;
+  int64_t total_response_content_size_ = 0;
 
   // Last time when the check for hanging requests was run.
   base::TimeTicks last_hanging_request_check_;
@@ -243,11 +243,11 @@
   // observations until Chromium is restarted. This may happen if the throughput
   // analyzer has lost track of the requests that degrade throughput computation
   // accuracy.
-  bool disable_throughput_measurements_;
+  bool disable_throughput_measurements_ = false;
 
   // Determines if the requests to local host can be used in estimating the
   // network quality. Set to true only for tests.
-  bool use_localhost_requests_for_tests_;
+  bool use_localhost_requests_for_tests_ = false;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/net/nqe/throughput_analyzer_unittest.cc b/net/nqe/throughput_analyzer_unittest.cc
index b24ca93..a156ce3a 100644
--- a/net/nqe/throughput_analyzer_unittest.cc
+++ b/net/nqe/throughput_analyzer_unittest.cc
@@ -80,9 +80,7 @@
                 &TestThroughputAnalyzer::OnNewThroughputObservationAvailable,
                 base::Unretained(this)),
             tick_clock,
-            NetLogWithSource::Make(NetLogSourceType::NONE)),
-        throughput_observations_received_(0),
-        bits_received_(0) {}
+            NetLogWithSource::Make(NetLogSourceType::NONE)) {}
 
   TestThroughputAnalyzer(const TestThroughputAnalyzer&) = delete;
   TestThroughputAnalyzer& operator=(const TestThroughputAnalyzer&) = delete;
@@ -110,9 +108,9 @@
   using internal::ThroughputAnalyzer::IsHangingWindow;
 
  private:
-  int throughput_observations_received_;
+  int throughput_observations_received_ = 0;
 
-  int64_t bits_received_;
+  int64_t bits_received_ = 0;
 };
 
 using ThroughputAnalyzerTest = TestWithTaskEnvironment;
diff --git a/net/ntlm/ntlm_buffer_writer.cc b/net/ntlm/ntlm_buffer_writer.cc
index efbbfb4..8f3f7221 100644
--- a/net/ntlm/ntlm_buffer_writer.cc
+++ b/net/ntlm/ntlm_buffer_writer.cc
@@ -16,7 +16,7 @@
 namespace ntlm {
 
 NtlmBufferWriter::NtlmBufferWriter(size_t buffer_len)
-    : buffer_(buffer_len, 0), cursor_(0) {}
+    : buffer_(buffer_len, 0) {}
 
 NtlmBufferWriter::~NtlmBufferWriter() = default;
 
diff --git a/net/ntlm/ntlm_buffer_writer.h b/net/ntlm/ntlm_buffer_writer.h
index f0afd00..00745ce 100644
--- a/net/ntlm/ntlm_buffer_writer.h
+++ b/net/ntlm/ntlm_buffer_writer.h
@@ -188,7 +188,7 @@
   uint8_t* GetBufferPtrAtCursor() { return GetBufferPtr() + GetCursor(); }
 
   std::vector<uint8_t> buffer_;
-  size_t cursor_;
+  size_t cursor_ = 0;
 };
 
 }  // namespace ntlm
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.cc b/net/proxy_resolution/configured_proxy_resolution_service.cc
index 04d8766..f1cab35 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service.cc
+++ b/net/proxy_resolution/configured_proxy_resolution_service.cc
@@ -419,10 +419,7 @@
 class ConfiguredProxyResolutionService::InitProxyResolver {
  public:
   InitProxyResolver()
-      : proxy_resolver_factory_(nullptr),
-        proxy_resolver_(nullptr),
-        next_state_(State::kNone),
-        quick_check_enabled_(true) {}
+      : proxy_resolver_factory_(nullptr), proxy_resolver_(nullptr) {}
 
   InitProxyResolver(const InitProxyResolver&) = delete;
   InitProxyResolver& operator=(const InitProxyResolver&) = delete;
@@ -607,8 +604,8 @@
   std::unique_ptr<ProxyResolverFactory::Request> create_resolver_request_;
   raw_ptr<std::unique_ptr<ProxyResolver>> proxy_resolver_;
   CompletionOnceCallback callback_;
-  State next_state_;
-  bool quick_check_enabled_;
+  State next_state_ = State::kNone;
+  bool quick_check_enabled_ = true;
 };
 
 // ConfiguredProxyResolutionService::PacFileDeciderPoller
@@ -837,8 +834,6 @@
     bool quick_check_enabled)
     : config_service_(std::move(config_service)),
       resolver_factory_(std::move(resolver_factory)),
-      current_state_(STATE_NONE),
-      permanent_error_(OK),
       net_log_(net_log),
       stall_proxy_auto_config_delay_(
           base::Milliseconds(kDelayAfterNetworkChangesMs)),
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.h b/net/proxy_resolution/configured_proxy_resolution_service.h
index 054b75d..83b5ee33 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service.h
+++ b/net/proxy_resolution/configured_proxy_resolution_service.h
@@ -19,6 +19,7 @@
 #include "base/threading/thread_checker.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/load_states.h"
+#include "net/base/net_errors.h"
 #include "net/base/net_export.h"
 #include "net/base/network_change_notifier.h"
 #include "net/log/net_log_with_source.h"
@@ -392,11 +393,11 @@
   // Helper to poll the PAC script for changes.
   std::unique_ptr<PacFileDeciderPoller> script_poller_;
 
-  State current_state_;
+  State current_state_ = STATE_NONE;
 
   // Either OK or an ERR_* value indicating that a permanent error (e.g.
   // failed to fetch the PAC script) prevents proxy resolution.
-  int permanent_error_;
+  int permanent_error_ = OK;
 
   // This is the log where any events generated by |init_proxy_resolver_| are
   // sent to.
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.cc b/net/proxy_resolution/mock_pac_file_fetcher.cc
index 77436d3..3aebe8bb 100644
--- a/net/proxy_resolution/mock_pac_file_fetcher.cc
+++ b/net/proxy_resolution/mock_pac_file_fetcher.cc
@@ -14,8 +14,7 @@
 
 namespace net {
 
-MockPacFileFetcher::MockPacFileFetcher()
-    : pending_request_text_(nullptr), is_shutdown_(false) {}
+MockPacFileFetcher::MockPacFileFetcher() : pending_request_text_(nullptr) {}
 
 MockPacFileFetcher::~MockPacFileFetcher() = default;
 
diff --git a/net/proxy_resolution/mock_pac_file_fetcher.h b/net/proxy_resolution/mock_pac_file_fetcher.h
index 5c4f14a7..c3142a187 100644
--- a/net/proxy_resolution/mock_pac_file_fetcher.h
+++ b/net/proxy_resolution/mock_pac_file_fetcher.h
@@ -46,7 +46,7 @@
   CompletionOnceCallback pending_request_callback_;
   raw_ptr<std::u16string> pending_request_text_;
   base::OnceClosure on_fetch_complete_;
-  bool is_shutdown_;
+  bool is_shutdown_ = false;
 };
 
 }  // namespace net
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
index f7dd6639..8ff6ab4 100644
--- a/net/proxy_resolution/multi_threaded_proxy_resolver.cc
+++ b/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -162,7 +162,7 @@
 
 class Job : public base::RefCountedThreadSafe<Job> {
  public:
-  Job() : executor_(nullptr), was_cancelled_(false) {}
+  Job() : executor_(nullptr) {}
 
   void set_executor(Executor* executor) {
     executor_ = executor;
@@ -209,7 +209,7 @@
 
  private:
   raw_ptr<Executor> executor_;
-  bool was_cancelled_;
+  bool was_cancelled_ = false;
 };
 
 class MultiThreadedProxyResolver::RequestImpl : public ProxyResolver::Request {
@@ -281,8 +281,7 @@
         results_(results),
         net_log_(net_log),
         url_(url),
-        network_isolation_key_(network_isolation_key),
-        was_waiting_for_thread_(false) {
+        network_isolation_key_(network_isolation_key) {
     DCHECK(callback_);
   }
 
@@ -348,7 +347,7 @@
   // Usable from within DoQuery on the worker thread.
   ProxyInfo results_buf_;
 
-  bool was_waiting_for_thread_;
+  bool was_waiting_for_thread_ = false;
 };
 
 // Executor ----------------------------------------
diff --git a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
index c792a46..30a80e5 100644
--- a/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
+++ b/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
@@ -111,7 +111,7 @@
     WILL_BLOCK,
   };
 
-  BlockableProxyResolver() : state_(State::NONE), condition_(&lock_) {}
+  BlockableProxyResolver() : condition_(&lock_) {}
 
   BlockableProxyResolver(const BlockableProxyResolver&) = delete;
   BlockableProxyResolver& operator=(const BlockableProxyResolver&) = delete;
@@ -172,7 +172,7 @@
   }
 
  private:
-  State state_;
+  State state_ = State::NONE;
   base::Lock lock_;
   base::ConditionVariable condition_;
 };
diff --git a/net/proxy_resolution/network_delegate_error_observer_unittest.cc b/net/proxy_resolution/network_delegate_error_observer_unittest.cc
index e30b0295..e545a905 100644
--- a/net/proxy_resolution/network_delegate_error_observer_unittest.cc
+++ b/net/proxy_resolution/network_delegate_error_observer_unittest.cc
@@ -23,7 +23,7 @@
 
 class TestNetworkDelegate : public NetworkDelegateImpl {
  public:
-  TestNetworkDelegate() : got_pac_error_(false) {}
+  TestNetworkDelegate() = default;
   ~TestNetworkDelegate() override = default;
 
   bool got_pac_error() const { return got_pac_error_; }
@@ -34,7 +34,7 @@
     got_pac_error_ = true;
   }
 
-  bool got_pac_error_;
+  bool got_pac_error_ = false;
 };
 
 // Check that the OnPACScriptError method can be called from an arbitrary
diff --git a/net/proxy_resolution/pac_file_decider.cc b/net/proxy_resolution/pac_file_decider.cc
index 6b4a2f5..b779e60 100644
--- a/net/proxy_resolution/pac_file_decider.cc
+++ b/net/proxy_resolution/pac_file_decider.cc
@@ -92,13 +92,8 @@
                                NetLog* net_log)
     : pac_file_fetcher_(pac_file_fetcher),
       dhcp_pac_file_fetcher_(dhcp_pac_file_fetcher),
-      current_pac_source_index_(0u),
-      pac_mandatory_(false),
-      next_state_(STATE_NONE),
-      net_log_(
-          NetLogWithSource::Make(net_log, NetLogSourceType::PAC_FILE_DECIDER)),
-      fetch_pac_bytes_(false),
-      quick_check_enabled_(true) {}
+      net_log_(NetLogWithSource::Make(net_log,
+                                      NetLogSourceType::PAC_FILE_DECIDER)) {}
 
 PacFileDecider::~PacFileDecider() {
   if (next_state_ != STATE_NONE)
diff --git a/net/proxy_resolution/pac_file_decider.h b/net/proxy_resolution/pac_file_decider.h
index f9aed53b..ca8debdd 100644
--- a/net/proxy_resolution/pac_file_decider.h
+++ b/net/proxy_resolution/pac_file_decider.h
@@ -186,24 +186,24 @@
 
   CompletionOnceCallback callback_;
 
-  size_t current_pac_source_index_;
+  size_t current_pac_source_index_ = 0u;
 
   // Filled when the PAC script fetch completes.
   std::u16string pac_script_;
 
   // Flag indicating whether the caller requested a mandatory PAC script
   // (i.e. fallback to direct connections are prohibited).
-  bool pac_mandatory_;
+  bool pac_mandatory_ = false;
 
   // Whether we have an existing custom PAC URL.
   bool have_custom_pac_url_;
 
   PacSourceList pac_sources_;
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   NetLogWithSource net_log_;
 
-  bool fetch_pac_bytes_;
+  bool fetch_pac_bytes_ = false;
 
   base::TimeDelta wait_delay_;
   base::OneShotTimer wait_timer_;
@@ -211,7 +211,7 @@
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
 
   // Whether to do DNS quick check
-  bool quick_check_enabled_;
+  bool quick_check_enabled_ = true;
 
   // Results.
   ProxyConfigWithAnnotation effective_config_;
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.cc b/net/proxy_resolution/pac_file_fetcher_impl.cc
index c0ffd19..e2a9114f 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl.cc
+++ b/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -318,9 +318,6 @@
 PacFileFetcherImpl::PacFileFetcherImpl(URLRequestContext* url_request_context)
     : url_request_context_(url_request_context),
       buf_(base::MakeRefCounted<IOBuffer>(kBufSize)),
-      next_id_(0),
-      cur_request_id_(0),
-      result_code_(OK),
       result_text_(nullptr),
       max_response_bytes_(kDefaultMaxResponseBytes),
       max_duration_(kDefaultMaxDuration) {
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.h b/net/proxy_resolution/pac_file_fetcher_impl.h
index e52fd0e..32ef8e61 100644
--- a/net/proxy_resolution/pac_file_fetcher_impl.h
+++ b/net/proxy_resolution/pac_file_fetcher_impl.h
@@ -116,7 +116,7 @@
   scoped_refptr<IOBuffer> buf_;
 
   // The next ID to use for |cur_request_| (monotonically increasing).
-  int next_id_;
+  int next_id_ = 0;
 
   // The current (in progress) request, or NULL.
   std::unique_ptr<URLRequest> cur_request_;
@@ -124,13 +124,13 @@
   // State for current request (only valid when |cur_request_| is not NULL):
 
   // Unique ID for the current request.
-  int cur_request_id_;
+  int cur_request_id_ = 0;
 
   // Callback to invoke on completion of the fetch.
   CompletionOnceCallback callback_;
 
   // Holds the error condition that was hit on the current request, or OK.
-  int result_code_;
+  int result_code_ = OK;
 
   // Holds the bytes read so far. Will not exceed |max_response_bytes|.
   std::string bytes_read_so_far_;
diff --git a/net/proxy_resolution/polling_proxy_config_service.cc b/net/proxy_resolution/polling_proxy_config_service.cc
index 01d66b4..a21d4cd 100644
--- a/net/proxy_resolution/polling_proxy_config_service.cc
+++ b/net/proxy_resolution/polling_proxy_config_service.cc
@@ -28,11 +28,7 @@
        const NetworkTrafficAnnotationTag& traffic_annotation)
       : get_config_func_(get_config_func),
         poll_interval_(poll_interval),
-        traffic_annotation_(traffic_annotation),
-        have_initialized_origin_runner_(false),
-        has_config_(false),
-        poll_task_outstanding_(false),
-        poll_task_queued_(false) {}
+        traffic_annotation_(traffic_annotation) {}
 
   // Called when the parent PollingProxyConfigService is destroyed
   // (observers should not be called past this point).
@@ -159,10 +155,10 @@
   base::Lock lock_;
   scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
 
-  bool have_initialized_origin_runner_;
-  bool has_config_;
-  bool poll_task_outstanding_;
-  bool poll_task_queued_;
+  bool have_initialized_origin_runner_ = false;
+  bool has_config_ = false;
+  bool poll_task_outstanding_ = false;
+  bool poll_task_queued_ = false;
 };
 
 void PollingProxyConfigService::AddObserver(Observer* observer) {
diff --git a/net/proxy_resolution/proxy_config.cc b/net/proxy_resolution/proxy_config.cc
index cf92c2c..5908492 100644
--- a/net/proxy_resolution/proxy_config.cc
+++ b/net/proxy_resolution/proxy_config.cc
@@ -41,10 +41,7 @@
 
 }  // namespace
 
-ProxyConfig::ProxyRules::ProxyRules()
-    : reverse_bypass(false),
-      type(Type::EMPTY) {
-}
+ProxyConfig::ProxyRules::ProxyRules() = default;
 
 ProxyConfig::ProxyRules::ProxyRules(const ProxyRules& other) = default;
 
@@ -210,7 +207,7 @@
   return nullptr;
 }
 
-ProxyConfig::ProxyConfig() : auto_detect_(false), pac_mandatory_(false) {}
+ProxyConfig::ProxyConfig() = default;
 
 ProxyConfig::ProxyConfig(const ProxyConfig& config) = default;
 
diff --git a/net/proxy_resolution/proxy_config.h b/net/proxy_resolution/proxy_config.h
index dac5572..17e364c 100644
--- a/net/proxy_resolution/proxy_config.h
+++ b/net/proxy_resolution/proxy_config.h
@@ -117,9 +117,9 @@
     ProxyBypassRules bypass_rules;
 
     // Reverse the meaning of |bypass_rules|.
-    bool reverse_bypass;
+    bool reverse_bypass = false;
 
-    Type type;
+    Type type = Type::EMPTY;
 
     // Set if |type| is Type::PROXY_LIST.
     ProxyList single_proxies;
@@ -225,7 +225,7 @@
 
  private:
   // True if the proxy configuration should be auto-detected.
-  bool auto_detect_;
+  bool auto_detect_ = false;
 
   // True if the proxy configuration was created from system settings.
   bool from_system_ = false;
@@ -235,7 +235,7 @@
 
   // If true, blocks all traffic in case fetching the PAC script from |pac_url_|
   // fails. Only valid if |pac_url_| is non-empty.
-  bool pac_mandatory_;
+  bool pac_mandatory_ = false;
 
   // Manual proxy settings.
   ProxyRules proxy_rules_;
diff --git a/net/proxy_resolution/proxy_config_service_linux.cc b/net/proxy_resolution/proxy_config_service_linux.cc
index 1a3b7d4..e2448a7 100644
--- a/net/proxy_resolution/proxy_config_service_linux.cc
+++ b/net/proxy_resolution/proxy_config_service_linux.cc
@@ -237,14 +237,7 @@
 class SettingGetterImplGSettings
     : public ProxyConfigServiceLinux::SettingGetter {
  public:
-  SettingGetterImplGSettings()
-      : client_(nullptr),
-        http_client_(nullptr),
-        https_client_(nullptr),
-        ftp_client_(nullptr),
-        socks_client_(nullptr),
-        notify_delegate_(nullptr),
-        debounce_timer_(new base::OneShotTimer()) {}
+  SettingGetterImplGSettings() : debounce_timer_(new base::OneShotTimer()) {}
 
   SettingGetterImplGSettings(const SettingGetterImplGSettings&) = delete;
   SettingGetterImplGSettings& operator=(const SettingGetterImplGSettings&) =
@@ -472,12 +465,12 @@
     setting_getter->OnChangeNotification();
   }
 
-  GSettings* client_;
-  GSettings* http_client_;
-  GSettings* https_client_;
-  GSettings* ftp_client_;
-  GSettings* socks_client_;
-  ProxyConfigServiceLinux::Delegate* notify_delegate_;
+  GSettings* client_ = nullptr;
+  GSettings* http_client_ = nullptr;
+  GSettings* https_client_ = nullptr;
+  GSettings* ftp_client_ = nullptr;
+  GSettings* socks_client_ = nullptr;
+  ProxyConfigServiceLinux::Delegate* notify_delegate_ = nullptr;
   std::unique_ptr<base::OneShotTimer> debounce_timer_;
 
   // Task runner for the thread that we make gsettings calls on. It should
@@ -522,12 +515,7 @@
 class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter {
  public:
   explicit SettingGetterImplKDE(base::Environment* env_var_getter)
-      : inotify_fd_(-1),
-        notify_delegate_(nullptr),
-        debounce_timer_(new base::OneShotTimer()),
-        indirect_manual_(false),
-        auto_no_pac_(false),
-        reversed_bypass_list_(false),
+      : debounce_timer_(new base::OneShotTimer()),
         env_var_getter_(env_var_getter),
         file_task_runner_(nullptr) {
     // This has to be called on the UI thread (http://crbug.com/69057).
@@ -1020,14 +1008,14 @@
   typedef std::map<StringListSetting,
                    std::vector<std::string> > strings_map_type;
 
-  int inotify_fd_;
+  int inotify_fd_ = -1;
   std::unique_ptr<base::FileDescriptorWatcher::Controller> inotify_watcher_;
-  ProxyConfigServiceLinux::Delegate* notify_delegate_;
+  ProxyConfigServiceLinux::Delegate* notify_delegate_ = nullptr;
   std::unique_ptr<base::OneShotTimer> debounce_timer_;
   std::vector<base::FilePath> kde_config_dirs_;
-  bool indirect_manual_;
-  bool auto_no_pac_;
-  bool reversed_bypass_list_;
+  bool indirect_manual_ = false;
+  bool auto_no_pac_ = false;
+  bool reversed_bypass_list_ = false;
   // We don't own |env_var_getter_|.  It's safe to hold a pointer to it, since
   // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the
   // same lifetime.
diff --git a/net/proxy_resolution/proxy_info.cc b/net/proxy_resolution/proxy_info.cc
index 2396fefa..f1e2f909 100644
--- a/net/proxy_resolution/proxy_info.cc
+++ b/net/proxy_resolution/proxy_info.cc
@@ -8,7 +8,7 @@
 
 namespace net {
 
-ProxyInfo::ProxyInfo() : did_bypass_proxy_(false) {}
+ProxyInfo::ProxyInfo() = default;
 
 ProxyInfo::ProxyInfo(const ProxyInfo& other) = default;
 
diff --git a/net/proxy_resolution/proxy_info.h b/net/proxy_resolution/proxy_info.h
index 69cae35..e2d926e 100644
--- a/net/proxy_resolution/proxy_info.h
+++ b/net/proxy_resolution/proxy_info.h
@@ -203,7 +203,7 @@
   MutableNetworkTrafficAnnotationTag traffic_annotation_;
 
   // Whether the proxy result represent a proxy bypass.
-  bool did_bypass_proxy_;
+  bool did_bypass_proxy_ = false;
 
   // How long it took to resolve the proxy.  Times are both null if proxy was
   // determined synchronously without running a PAC.
diff --git a/net/quic/bidirectional_stream_quic_impl.cc b/net/quic/bidirectional_stream_quic_impl.cc
index 2c70a2bd..befaf5538 100644
--- a/net/quic/bidirectional_stream_quic_impl.cc
+++ b/net/quic/bidirectional_stream_quic_impl.cc
@@ -43,18 +43,7 @@
     : session_(std::move(session)),
       stream_(nullptr),
       request_info_(nullptr),
-      delegate_(nullptr),
-      response_status_(OK),
-      negotiated_protocol_(kProtoUnknown),
-      read_buffer_len_(0),
-      headers_bytes_received_(0),
-      headers_bytes_sent_(0),
-      closed_stream_received_bytes_(0),
-      closed_stream_sent_bytes_(0),
-      closed_is_first_stream_(false),
-      has_sent_headers_(false),
-      send_request_headers_automatically_(true),
-      may_invoke_callbacks_(true) {}
+      delegate_(nullptr) {}
 
 BidirectionalStreamQuicImpl::~BidirectionalStreamQuicImpl() {
   if (stream_) {
diff --git a/net/quic/bidirectional_stream_quic_impl.h b/net/quic/bidirectional_stream_quic_impl.h
index 834babd..eb54b1f6 100644
--- a/net/quic/bidirectional_stream_quic_impl.h
+++ b/net/quic/bidirectional_stream_quic_impl.h
@@ -91,10 +91,10 @@
   // Saves the response status if the stream is explicitly closed via OnError
   // or OnClose with an error. Once all buffered data has been returned, this
   // will be used as the final response.
-  int response_status_;
+  int response_status_ = OK;
 
   // The protocol that is negotiated.
-  NextProto negotiated_protocol_;
+  NextProto negotiated_protocol_ = kProtoUnknown;
   // Connect timing information for this stream. Populated when headers are
   // received.
   LoadTimingInfo::ConnectTiming connect_timing_;
@@ -104,33 +104,33 @@
 
   // User provided read buffer for ReadData() response.
   scoped_refptr<IOBuffer> read_buffer_;
-  int read_buffer_len_;
+  int read_buffer_len_ = 0;
 
   // Number of bytes received by the headers stream on behalf of this stream.
-  int64_t headers_bytes_received_;
+  int64_t headers_bytes_received_ = 0;
   // Number of bytes sent by the headers stream on behalf of this stream.
-  int64_t headers_bytes_sent_;
+  int64_t headers_bytes_sent_ = 0;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes received over the network for |stream_| while it was open.
-  int64_t closed_stream_received_bytes_;
+  int64_t closed_stream_received_bytes_ = 0;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes sent over the network for |stream_| while it was open.
-  int64_t closed_stream_sent_bytes_;
+  int64_t closed_stream_sent_bytes_ = 0;
   // True if the stream is the first stream negotiated on the session. Set when
   // the stream was closed. If |stream_| is failed to be created, this takes on
   // the default value of false.
-  bool closed_is_first_stream_;
+  bool closed_is_first_stream_ = false;
   // Indicates whether initial headers have been sent.
-  bool has_sent_headers_;
+  bool has_sent_headers_ = false;
 
   // Whether to automatically send request headers when stream is negotiated.
   // If false, headers will not be sent until SendRequestHeaders() is called or
   // until next SendData/SendvData, during which QUIC will try to combine header
   // frame with data frame in the same packet if possible.
-  bool send_request_headers_automatically_;
+  bool send_request_headers_automatically_ = true;
 
   // True when callbacks to the delegate may be invoked synchronously.
-  bool may_invoke_callbacks_;
+  bool may_invoke_callbacks_ = true;
 
   base::WeakPtrFactory<BidirectionalStreamQuicImpl> weak_factory_{this};
 };
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 3525e3d5..e7132c61 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -460,7 +460,6 @@
                       kDefaultServerHostName,
                       quic::Perspective::IS_CLIENT,
                       client_headers_include_h2_stream_dependency_),
-        packet_number_(0),
         server_maker_(version_,
                       connection_id_,
                       &clock_,
@@ -852,7 +851,7 @@
   const quic::QuicConnectionId connection_id_;
   const quic::QuicStreamId stream_id_;
   QuicTestPacketMaker client_maker_;
-  uint64_t packet_number_;
+  uint64_t packet_number_ = 0;
   QuicTestPacketMaker server_maker_;
   IPEndPoint self_addr_;
   IPEndPoint peer_addr_;
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 0b7c958..f6fdcc5 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -34,8 +34,7 @@
 
 namespace net {
 
-ProofVerifyDetailsChromium::ProofVerifyDetailsChromium()
-    : pkp_bypassed(false), is_fatal_cert_error(false) {}
+ProofVerifyDetailsChromium::ProofVerifyDetailsChromium() = default;
 
 ProofVerifyDetailsChromium::~ProofVerifyDetailsChromium() {}
 
@@ -165,7 +164,7 @@
   // passed to CertVerifier::Verify.
   int cert_verify_flags_;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   base::TimeTicks start_time_;
 
@@ -186,7 +185,6 @@
       transport_security_state_(transport_security_state),
       sct_auditing_delegate_(sct_auditing_delegate),
       cert_verify_flags_(cert_verify_flags),
-      next_state_(STATE_NONE),
       start_time_(base::TimeTicks::Now()),
       net_log_(net_log) {
   CHECK(proof_verifier_);
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index fb14c67..57a6ae7 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -47,11 +47,11 @@
   std::string pinning_failure_log;
 
   // True if PKP was bypassed due to a local trust anchor.
-  bool pkp_bypassed;
+  bool pkp_bypassed = false;
 
   // True if there was a certificate error which should be treated as fatal,
   // and false otherwise.
-  bool is_fatal_cert_error;
+  bool is_fatal_cert_error = false;
 };
 
 // ProofVerifyContextChromium is the implementation-specific information that a
diff --git a/net/quic/mock_crypto_client_stream.cc b/net/quic/mock_crypto_client_stream.cc
index f4c3d8f..8183255 100644
--- a/net/quic/mock_crypto_client_stream.cc
+++ b/net/quic/mock_crypto_client_stream.cc
@@ -71,8 +71,6 @@
                              /*has_application_state = */ true),
       QuicCryptoHandshaker(this, session),
       handshake_mode_(handshake_mode),
-      encryption_established_(false),
-      handshake_confirmed_(false),
       crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
       use_mock_crypter_(use_mock_crypter),
       server_id_(server_id),
diff --git a/net/quic/mock_crypto_client_stream.h b/net/quic/mock_crypto_client_stream.h
index eef99bd..d6bf54b 100644
--- a/net/quic/mock_crypto_client_stream.h
+++ b/net/quic/mock_crypto_client_stream.h
@@ -101,8 +101,8 @@
   void FillCryptoParams();
 
   HandshakeMode handshake_mode_;
-  bool encryption_established_;
-  bool handshake_confirmed_;
+  bool encryption_established_ = false;
+  bool handshake_confirmed_ = false;
   quiche::QuicheReferenceCountedPointer<quic::QuicCryptoNegotiatedParameters>
       crypto_negotiated_params_;
   quic::CryptoFramer crypto_framer_;
diff --git a/net/quic/mock_crypto_client_stream_factory.cc b/net/quic/mock_crypto_client_stream_factory.cc
index 9ff68c6..3b50b76 100644
--- a/net/quic/mock_crypto_client_stream_factory.cc
+++ b/net/quic/mock_crypto_client_stream_factory.cc
@@ -15,10 +15,7 @@
 MockCryptoClientStreamFactory::~MockCryptoClientStreamFactory() {}
 
 MockCryptoClientStreamFactory::MockCryptoClientStreamFactory()
-    : handshake_mode_(MockCryptoClientStream::CONFIRM_HANDSHAKE),
-      last_stream_(nullptr),
-      config_(new quic::QuicConfig()),
-      use_mock_crypter_(false) {}
+    : last_stream_(nullptr), config_(new quic::QuicConfig()) {}
 
 void MockCryptoClientStreamFactory::SetConfig(const quic::QuicConfig& config) {
   config_ = std::make_unique<quic::QuicConfig>(config);
diff --git a/net/quic/mock_crypto_client_stream_factory.h b/net/quic/mock_crypto_client_stream_factory.h
index e27d9b1..540660cc 100644
--- a/net/quic/mock_crypto_client_stream_factory.h
+++ b/net/quic/mock_crypto_client_stream_factory.h
@@ -56,11 +56,12 @@
   void SetConfig(const quic::QuicConfig& config);
 
  private:
-  MockCryptoClientStream::HandshakeMode handshake_mode_;
+  MockCryptoClientStream::HandshakeMode handshake_mode_ =
+      MockCryptoClientStream::CONFIRM_HANDSHAKE;
   raw_ptr<MockCryptoClientStream> last_stream_;
   base::queue<const ProofVerifyDetailsChromium*> proof_verify_details_queue_;
   std::unique_ptr<quic::QuicConfig> config_;
-  bool use_mock_crypter_;
+  bool use_mock_crypter_ = false;
 };
 
 }  // namespace net
diff --git a/net/quic/mock_quic_data.cc b/net/quic/mock_quic_data.cc
index c6f3af3..0ba04e7bc 100644
--- a/net/quic/mock_quic_data.cc
+++ b/net/quic/mock_quic_data.cc
@@ -9,7 +9,7 @@
 namespace test {
 
 MockQuicData::MockQuicData(quic::ParsedQuicVersion version)
-    : sequence_number_(0), printer_(version) {}
+    : printer_(version) {}
 
 MockQuicData::~MockQuicData() {}
 
diff --git a/net/quic/mock_quic_data.h b/net/quic/mock_quic_data.h
index b887388..6c87c68 100644
--- a/net/quic/mock_quic_data.h
+++ b/net/quic/mock_quic_data.h
@@ -68,7 +68,7 @@
   std::unique_ptr<MockConnect> connect_;
   std::vector<MockWrite> writes_;
   std::vector<MockRead> reads_;
-  size_t sequence_number_;
+  size_t sequence_number_ = 0;
   std::unique_ptr<SequencedSocketData> socket_data_;
   QuicPacketPrinter printer_;
 };
diff --git a/net/quic/network_connection.cc b/net/quic/network_connection.cc
index b545829..970a5cc 100644
--- a/net/quic/network_connection.cc
+++ b/net/quic/network_connection.cc
@@ -9,9 +9,7 @@
 
 namespace net {
 
-NetworkConnection::NetworkConnection()
-    : connection_type_(NetworkChangeNotifier::CONNECTION_UNKNOWN),
-      connection_description_(nullptr) {
+NetworkConnection::NetworkConnection() {
   NetworkChangeNotifier::AddIPAddressObserver(this);
   NetworkChangeNotifier::AddConnectionTypeObserver(this);
   OnIPAddressChanged();
diff --git a/net/quic/network_connection.h b/net/quic/network_connection.h
index 589a88b6..e2ea747 100644
--- a/net/quic/network_connection.h
+++ b/net/quic/network_connection.h
@@ -49,10 +49,11 @@
  private:
   // Cache the connection type to avoid calling the potentially expensive
   // NetworkChangeNotifier::GetConnectionType() function.
-  NetworkChangeNotifier::ConnectionType connection_type_;
+  NetworkChangeNotifier::ConnectionType connection_type_ =
+      NetworkChangeNotifier::CONNECTION_UNKNOWN;
   // Cache the connection description string to avoid calling the expensive
   // GetWifiPHYLayerProtocol() function.
-  const char* connection_description_;
+  const char* connection_description_ = nullptr;
 };
 
 }  // namespace net
diff --git a/net/quic/quic_chromium_alarm_factory_test.cc b/net/quic/quic_chromium_alarm_factory_test.cc
index 729b814..1f74a825 100644
--- a/net/quic/quic_chromium_alarm_factory_test.cc
+++ b/net/quic/quic_chromium_alarm_factory_test.cc
@@ -14,7 +14,7 @@
 
 class TestDelegate : public quic::QuicAlarm::DelegateWithoutContext {
  public:
-  TestDelegate() : fired_(false) {}
+  TestDelegate() = default;
 
   void OnAlarm() override { fired_ = true; }
 
@@ -22,7 +22,7 @@
   void Clear() { fired_ = false; }
 
  private:
-  bool fired_;
+  bool fired_ = false;
 };
 
 class QuicChromiumAlarmFactoryTest : public ::testing::Test {
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index 36b8f36..918f5e05 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -367,13 +367,8 @@
       destination_(std::move(destination)),
       net_log_(session_->net_log()),
       was_handshake_confirmed_(session->OneRttKeysAvailable()),
-      net_error_(OK),
-      quic_error_(quic::QUIC_NO_ERROR),
-      port_migration_detected_(false),
       server_id_(session_->server_id()),
-      quic_version_(session->connection()->version()),
-      push_handle_(nullptr),
-      was_ever_used_(false) {
+      quic_version_(session->connection()->version()) {
   DCHECK(session_);
   session_->AddHandle(this);
 }
@@ -957,10 +952,8 @@
       max_time_on_non_default_network_(max_time_on_non_default_network),
       max_migrations_to_non_default_network_on_write_error_(
           max_migrations_to_non_default_network_on_write_error),
-      current_migrations_to_non_default_network_on_write_error_(0),
       max_migrations_to_non_default_network_on_path_degrading_(
           max_migrations_to_non_default_network_on_path_degrading),
-      current_migrations_to_non_default_network_on_path_degrading_(0),
       clock_(clock),
       yield_after_packets_(yield_after_packets),
       yield_after_duration_(yield_after_duration),
@@ -968,16 +961,12 @@
       most_recent_network_disconnected_timestamp_(base::TimeTicks()),
       tick_clock_(tick_clock),
       most_recent_stream_close_time_(tick_clock_->NowTicks()),
-      most_recent_write_error_(0),
       most_recent_write_error_timestamp_(base::TimeTicks()),
       crypto_config_(std::move(crypto_config)),
       stream_factory_(stream_factory),
       transport_security_state_(transport_security_state),
       ssl_config_service_(ssl_config_service),
       server_info_(std::move(server_info)),
-      pkp_bypassed_(false),
-      is_fatal_cert_error_(false),
-      num_total_streams_(0),
       task_runner_(task_runner),
       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::QUIC_SESSION)),
       logger_(new QuicConnectionLogger(this,
@@ -987,23 +976,9 @@
       http3_logger_(VersionUsesHttp3(connection->transport_version())
                         ? new QuicHttp3Logger(net_log_)
                         : nullptr),
-      going_away_(false),
-      port_migration_detected_(false),
       push_delegate_(push_delegate),
-      streams_pushed_count_(0),
-      streams_pushed_and_claimed_count_(0),
-      bytes_pushed_count_(0),
-      bytes_pushed_and_unclaimed_count_(0),
-      retry_migrate_back_count_(0),
-      current_migration_cause_(UNKNOWN_CAUSE),
-      send_packet_after_migration_(false),
-      wait_for_new_network_(false),
-      ignore_read_error_(false),
       headers_include_h2_stream_dependency_(
           headers_include_h2_stream_dependency),
-      attempted_zero_rtt_(false),
-      num_migrations_(0),
-      last_key_update_reason_(quic::KeyUpdateReason::kInvalid),
       push_promise_index_(std::move(push_promise_index)),
       path_validation_writer_delegate_(this, task_runner_) {
   default_network_ = default_network;
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index 58c70a036..f1a38c3 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -333,9 +333,9 @@
     // session is destroyed.
     NetLogWithSource net_log_;
     bool was_handshake_confirmed_;
-    int net_error_;
-    quic::QuicErrorCode quic_error_;
-    bool port_migration_detected_;
+    int net_error_ = OK;
+    quic::QuicErrorCode quic_error_ = quic::QUIC_NO_ERROR;
+    bool port_migration_detected_ = false;
     quic::QuicServerId server_id_;
     quic::ParsedQuicVersion quic_version_;
     LoadTimingInfo::ConnectTiming connect_timing_;
@@ -345,11 +345,11 @@
     // is asynchronous, i.e. it returned quic::QUIC_PENDING, and remains valid
     // until |OnRendezvouResult()| fires or |push_handle_->Cancel()| is
     // invoked.
-    quic::QuicClientPushPromiseIndex::TryHandle* push_handle_;
+    quic::QuicClientPushPromiseIndex::TryHandle* push_handle_ = nullptr;
     CompletionOnceCallback push_callback_;
     std::unique_ptr<QuicChromiumClientStream::Handle> push_stream_;
 
-    bool was_ever_used_;
+    bool was_ever_used_ = false;
   };
 
   // A helper class used to manage a request to create a stream.
@@ -971,11 +971,11 @@
   // Maximum allowed number of migrations to non-default network triggered by
   // packet write error per default network.
   int max_migrations_to_non_default_network_on_write_error_;
-  int current_migrations_to_non_default_network_on_write_error_;
+  int current_migrations_to_non_default_network_on_write_error_ = 0;
   // Maximum allowed number of migrations to non-default network triggered by
   // path degrading per default network.
   int max_migrations_to_non_default_network_on_path_degrading_;
-  int current_migrations_to_non_default_network_on_path_degrading_;
+  int current_migrations_to_non_default_network_on_path_degrading_ = 0;
   raw_ptr<const quic::QuicClock> clock_;  // Unowned.
   int yield_after_packets_;
   quic::QuicTime::Delta yield_after_duration_;
@@ -985,7 +985,7 @@
   raw_ptr<const base::TickClock> tick_clock_;
   base::TimeTicks most_recent_stream_close_time_;
 
-  int most_recent_write_error_;
+  int most_recent_write_error_ = 0;
   base::TimeTicks most_recent_write_error_timestamp_;
 
   std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_;
@@ -999,13 +999,13 @@
   std::unique_ptr<QuicServerInfo> server_info_;
   std::unique_ptr<CertVerifyResult> cert_verify_result_;
   std::string pinning_failure_log_;
-  bool pkp_bypassed_;
-  bool is_fatal_cert_error_;
+  bool pkp_bypassed_ = false;
+  bool is_fatal_cert_error_ = false;
   HandleSet handles_;
   StreamRequestQueue stream_requests_;
   std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_;
   CompletionOnceCallback callback_;
-  size_t num_total_streams_;
+  size_t num_total_streams_ = 0;
   raw_ptr<base::SequencedTaskRunner> task_runner_;
   NetLogWithSource net_log_;
   std::vector<std::unique_ptr<QuicChromiumPacketReader>> packet_readers_;
@@ -1014,17 +1014,17 @@
   std::unique_ptr<QuicHttp3Logger> http3_logger_;
   // True when the session is going away, and streams may no longer be created
   // on this session. Existing stream will continue to be processed.
-  bool going_away_;
+  bool going_away_ = false;
   // True when the session receives a go away from server due to port migration.
-  bool port_migration_detected_;
+  bool port_migration_detected_ = false;
   // Not owned. |push_delegate_| outlives the session and handles server pushes
   // received by session.
   raw_ptr<ServerPushDelegate> push_delegate_;
   // UMA histogram counters for streams pushed to this session.
-  int streams_pushed_count_;
-  int streams_pushed_and_claimed_count_;
-  uint64_t bytes_pushed_count_;
-  uint64_t bytes_pushed_and_unclaimed_count_;
+  int streams_pushed_count_ = 0;
+  int streams_pushed_and_claimed_count_ = 0;
+  uint64_t bytes_pushed_count_ = 0;
+  uint64_t bytes_pushed_and_unclaimed_count_ = 0;
   // Stores the packet that witnesses socket write error. This packet will be
   // written to an alternate socket when the migration completes and the
   // alternate socket is unblocked.
@@ -1032,32 +1032,33 @@
   // Stores the latest default network platform marks if migration is enabled.
   // Otherwise, stores the network interface that is used by the connection.
   NetworkChangeNotifier::NetworkHandle default_network_;
-  int retry_migrate_back_count_;
+  int retry_migrate_back_count_ = 0;
   base::OneShotTimer migrate_back_to_default_timer_;
-  MigrationCause current_migration_cause_;
+  MigrationCause current_migration_cause_ = UNKNOWN_CAUSE;
   // True if a packet needs to be sent when packet writer is unblocked to
   // complete connection migration. The packet can be a cached packet if
   // |packet_| is set, a queued packet, or a PING packet.
-  bool send_packet_after_migration_;
+  bool send_packet_after_migration_ = false;
   // True if migration is triggered, and there is no alternate network to
   // migrate to.
-  bool wait_for_new_network_;
+  bool wait_for_new_network_ = false;
   // True if read errors should be ignored. Set when migration on write error is
   // posted and unset until the first packet is written after migration.
-  bool ignore_read_error_;
+  bool ignore_read_error_ = false;
 
   // If true, client headers will include HTTP/2 stream dependency info derived
   // from spdy::SpdyStreamPrecedence.
   bool headers_include_h2_stream_dependency_;
   Http2PriorityDependencies priority_dependency_state_;
 
-  bool attempted_zero_rtt_;
+  bool attempted_zero_rtt_ = false;
 
-  size_t num_migrations_;
+  size_t num_migrations_ = 0;
 
   // The reason for the last 1-RTT key update on the connection. Will be
   // kInvalid if no key updates have occurred.
-  quic::KeyUpdateReason last_key_update_reason_;
+  quic::KeyUpdateReason last_key_update_reason_ =
+      quic::KeyUpdateReason::kInvalid;
 
   std::unique_ptr<quic::QuicClientPushPromiseIndex> push_promise_index_;
 
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 4439774..ffba0e1 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -161,8 +161,7 @@
                       &clock_,
                       kServerHostname,
                       quic::Perspective::IS_SERVER,
-                      false),
-        migrate_session_early_v2_(false) {
+                      false) {
     FLAGS_quic_enable_http3_grease_randomness = false;
     quic::QuicEnableVersion(version_);
     // Advance the time, because timers do not like uninitialized times.
@@ -314,7 +313,7 @@
   QuicTestPacketMaker client_maker_;
   QuicTestPacketMaker server_maker_;
   ProofVerifyDetailsChromium verify_details_;
-  bool migrate_session_early_v2_;
+  bool migrate_session_early_v2_ = false;
   quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
 };
 
diff --git a/net/quic/quic_chromium_client_stream.cc b/net/quic/quic_chromium_client_stream.cc
index e4fb1556..9767668 100644
--- a/net/quic/quic_chromium_client_stream.cc
+++ b/net/quic/quic_chromium_client_stream.cc
@@ -46,10 +46,7 @@
 
 QuicChromiumClientStream::Handle::Handle(QuicChromiumClientStream* stream)
     : stream_(stream),
-      may_invoke_callbacks_(true),
       read_headers_buffer_(nullptr),
-      read_body_buffer_len_(0),
-      net_error_(ERR_UNEXPECTED),
       net_log_(stream->net_log()) {
   SaveState();
 }
diff --git a/net/quic/quic_chromium_client_stream.h b/net/quic/quic_chromium_client_stream.h
index c1ff6d3f..fbf9299 100644
--- a/net/quic/quic_chromium_client_stream.h
+++ b/net/quic/quic_chromium_client_stream.h
@@ -178,7 +178,7 @@
 
     raw_ptr<QuicChromiumClientStream> stream_;  // Unowned.
 
-    bool may_invoke_callbacks_;  // True when callbacks may be invoked.
+    bool may_invoke_callbacks_ = true;  // True when callbacks may be invoked.
 
     // Callback to be invoked when ReadInitialHeaders completes asynchronously.
     CompletionOnceCallback read_headers_callback_;
@@ -188,7 +188,7 @@
     // Callback to be invoked when ReadBody completes asynchronously.
     CompletionOnceCallback read_body_callback_;
     raw_ptr<IOBuffer> read_body_buffer_;
-    int read_body_buffer_len_;
+    int read_body_buffer_len_ = 0;
 
     // Callback to be invoked when WriteStreamData or WritevStreamData completes
     // asynchronously.
@@ -206,7 +206,7 @@
     size_t num_bytes_consumed_;
     Idempotency idempotency_ = DEFAULT_IDEMPOTENCY;
 
-    int net_error_;
+    int net_error_ = ERR_UNEXPECTED;
 
     NetLogWithSource net_log_;
 
diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc
index 0f1a9987..b2756f9 100644
--- a/net/quic/quic_chromium_packet_reader.cc
+++ b/net/quic/quic_chromium_packet_reader.cc
@@ -31,8 +31,6 @@
     const NetLogWithSource& net_log)
     : socket_(socket),
       visitor_(visitor),
-      read_pending_(false),
-      num_packets_read_(0),
       clock_(clock),
       yield_after_packets_(yield_after_packets),
       yield_after_duration_(yield_after_duration),
diff --git a/net/quic/quic_chromium_packet_reader.h b/net/quic/quic_chromium_packet_reader.h
index 701d2f7..bdb54b2 100644
--- a/net/quic/quic_chromium_packet_reader.h
+++ b/net/quic/quic_chromium_packet_reader.h
@@ -65,8 +65,8 @@
   raw_ptr<DatagramClientSocket> socket_;
 
   raw_ptr<Visitor> visitor_;
-  bool read_pending_;
-  int num_packets_read_;
+  bool read_pending_ = false;
+  int num_packets_read_ = 0;
   raw_ptr<const quic::QuicClock> clock_;  // Not owned.
   int yield_after_packets_;
   quic::QuicTime::Delta yield_after_duration_;
diff --git a/net/quic/quic_chromium_packet_writer.cc b/net/quic/quic_chromium_packet_writer.cc
index e575096..a9c070cd 100644
--- a/net/quic/quic_chromium_packet_writer.cc
+++ b/net/quic/quic_chromium_packet_writer.cc
@@ -69,7 +69,7 @@
 }  // namespace
 
 QuicChromiumPacketWriter::ReusableIOBuffer::ReusableIOBuffer(size_t capacity)
-    : IOBuffer(capacity), capacity_(capacity), size_(0) {}
+    : IOBuffer(capacity), capacity_(capacity) {}
 
 QuicChromiumPacketWriter::ReusableIOBuffer::~ReusableIOBuffer() {}
 
diff --git a/net/quic/quic_chromium_packet_writer.h b/net/quic/quic_chromium_packet_writer.h
index 80e5a9e..1781d34 100644
--- a/net/quic/quic_chromium_packet_writer.h
+++ b/net/quic/quic_chromium_packet_writer.h
@@ -44,7 +44,7 @@
    private:
     ~ReusableIOBuffer() override;
     size_t capacity_;
-    size_t size_;
+    size_t size_ = 0;
   };
   // Delegate interface which receives notifications on socket write events.
   class NET_EXPORT_PRIVATE Delegate {
diff --git a/net/quic/quic_connection_logger.cc b/net/quic/quic_connection_logger.cc
index ccf6585..2bddbdf9 100644
--- a/net/quic/quic_connection_logger.cc
+++ b/net/quic/quic_connection_logger.cc
@@ -62,19 +62,6 @@
     std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher,
     const NetLogWithSource& net_log)
     : session_(session),
-      last_received_packet_size_(0),
-      no_packet_received_after_ping_(false),
-      previous_received_packet_size_(0),
-      num_out_of_order_received_packets_(0),
-      num_out_of_order_large_received_packets_(0),
-      num_packets_received_(0),
-      num_frames_received_(0),
-      num_duplicate_frames_received_(0),
-      num_incorrect_connection_ids_(0),
-      num_undecryptable_packets_(0),
-      num_duplicate_packets_(0),
-      num_blocked_frames_received_(0),
-      num_blocked_frames_sent_(0),
       connection_description_(connection_description),
       socket_performance_watcher_(std::move(socket_performance_watcher)),
       event_logger_(session, net_log) {}
diff --git a/net/quic/quic_connection_logger.h b/net/quic/quic_connection_logger.h
index ea58d8fe..f070213 100644
--- a/net/quic/quic_connection_logger.h
+++ b/net/quic/quic_connection_logger.h
@@ -154,11 +154,11 @@
   // The last packet number received.
   quic::QuicPacketNumber last_received_packet_number_;
   // The size of the most recently received packet.
-  size_t last_received_packet_size_;
+  size_t last_received_packet_size_ = 0;
   // True if a PING frame has been sent and no packet has been received.
-  bool no_packet_received_after_ping_;
+  bool no_packet_received_after_ping_ = false;
   // The size of the previously received packet.
-  size_t previous_received_packet_size_;
+  size_t previous_received_packet_size_ = 0;
   // The first received packet number. Used as the left edge of
   // received_packets_ and received_acks_. In the case where packets are
   // received out of order, packets with numbers smaller than
@@ -169,35 +169,35 @@
   quic::QuicPacketNumber largest_received_packet_number_;
   // Number of times that the current received packet number is
   // smaller than the last received packet number.
-  size_t num_out_of_order_received_packets_;
+  size_t num_out_of_order_received_packets_ = 0;
   // Number of times that the current received packet number is
   // smaller than the last received packet number and where the
   // size of the current packet is larger than the size of the previous
   // packet.
-  size_t num_out_of_order_large_received_packets_;
+  size_t num_out_of_order_large_received_packets_ = 0;
   // The number of times that OnPacketHeader was called.
   // If the network replicates packets, then this number may be slightly
   // different from the real number of distinct packets received.
-  quic::QuicPacketCount num_packets_received_;
+  quic::QuicPacketCount num_packets_received_ = 0;
   // The quic::kCADR value provided by the server in ServerHello.
   IPEndPoint local_address_from_shlo_;
   // The first local address from which a packet was received.
   IPEndPoint local_address_from_self_;
   // Count of the number of frames received.
-  int num_frames_received_;
+  int num_frames_received_ = 0;
   // Count of the number of duplicate frames received.
-  int num_duplicate_frames_received_;
+  int num_duplicate_frames_received_ = 0;
   // Count of the number of packets received with incorrect connection IDs.
-  int num_incorrect_connection_ids_;
+  int num_incorrect_connection_ids_ = 0;
   // Count of the number of undecryptable packets received.
-  int num_undecryptable_packets_;
+  int num_undecryptable_packets_ = 0;
   // Count of the number of duplicate packets received.
-  int num_duplicate_packets_;
+  int num_duplicate_packets_ = 0;
   // Count of the number of BLOCKED frames received.
-  int num_blocked_frames_received_;
+  int num_blocked_frames_received_ = 0;
   // Count of the number of BLOCKED frames sent.
-  int num_blocked_frames_sent_;
-  // Vector of inital packets status' indexed by packet numbers, where
+  int num_blocked_frames_sent_ = 0;
+  // Vector of initial packets status' indexed by packet numbers, where
   // false means never received. We track 150 packets starting from
   // first_received_packet_number_.
   std::bitset<150> received_packets_;
diff --git a/net/quic/quic_end_to_end_unittest.cc b/net/quic/quic_end_to_end_unittest.cc
index 27170337..c8c982d6 100644
--- a/net/quic/quic_end_to_end_unittest.cc
+++ b/net/quic/quic_end_to_end_unittest.cc
@@ -93,8 +93,7 @@
         ssl_config_service_(new SSLConfigServiceDefaults),
         proxy_resolution_service_(
             ConfiguredProxyResolutionService::CreateDirect()),
-        auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
-        strike_register_no_startup_period_(false) {
+        auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()) {
     request_.method = "GET";
     request_.url = GURL("https://test.example.com/");
     request_.load_flags = 0;
@@ -237,7 +236,7 @@
   quic::QuicConfig server_config_;
   quic::QuicCryptoServerConfig::ConfigOptions server_config_options_;
   bool server_started_;
-  bool strike_register_no_startup_period_;
+  bool strike_register_no_startup_period_ = false;
 };
 
 TEST_F(QuicEndToEndTest, LargeGetWithNoPacketLoss) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index 3964b05d..f3ba9a4 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -62,26 +62,10 @@
     std::unique_ptr<QuicChromiumClientSession::Handle> session,
     std::set<std::string> dns_aliases)
     : MultiplexedHttpStream(std::move(session)),
-      next_state_(STATE_NONE),
       stream_(nullptr),
       request_info_(nullptr),
-      can_send_early_(false),
       request_body_stream_(nullptr),
-      priority_(MINIMUM_PRIORITY),
       response_info_(nullptr),
-      has_response_status_(false),
-      response_status_(ERR_UNEXPECTED),
-      response_headers_received_(false),
-      trailing_headers_received_(false),
-      headers_bytes_received_(0),
-      headers_bytes_sent_(0),
-      closed_stream_received_bytes_(0),
-      closed_stream_sent_bytes_(0),
-      closed_is_first_stream_(false),
-      user_buffer_len_(0),
-      session_error_(ERR_UNEXPECTED),
-      found_promise_(false),
-      in_loop_(false),
       dns_aliases_(std::move(dns_aliases)) {}
 
 QuicHttpStream::~QuicHttpStream() {
diff --git a/net/quic/quic_http_stream.h b/net/quic/quic_http_stream.h
index e6ceaf7..e4dfa0d0 100644
--- a/net/quic/quic_http_stream.h
+++ b/net/quic/quic_http_stream.h
@@ -151,7 +151,7 @@
     return static_cast<const QuicChromiumClientSession::Handle*>(session());
   }
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   std::unique_ptr<QuicChromiumClientStream::Handle> stream_;
 
@@ -163,53 +163,53 @@
   raw_ptr<const HttpRequestInfo> request_info_;
 
   // Whether this request can be sent without confirmation.
-  bool can_send_early_;
+  bool can_send_early_ = false;
 
   // The request body to send, if any, owned by the caller.
   raw_ptr<UploadDataStream> request_body_stream_;
   // Time the request was issued.
   base::Time request_time_;
   // The priority of the request.
-  RequestPriority priority_;
+  RequestPriority priority_ = MINIMUM_PRIORITY;
   // |response_info_| is the HTTP response data object which is filled in
   // when a the response headers are read.  It is not owned by this stream.
   raw_ptr<HttpResponseInfo> response_info_;
-  bool has_response_status_;  // true if response_status_ as been set.
+  bool has_response_status_ = false;  // true if response_status_ as been set.
   // Because response data is buffered, also buffer the response status if the
   // stream is explicitly closed via OnError or OnClose with an error.
   // Once all buffered data has been returned, this will be used as the final
   // response.
-  int response_status_;
+  int response_status_ = ERR_UNEXPECTED;
 
   // Serialized request headers.
   spdy::Http2HeaderBlock request_headers_;
 
   spdy::Http2HeaderBlock response_header_block_;
-  bool response_headers_received_;
+  bool response_headers_received_ = false;
 
   spdy::Http2HeaderBlock trailing_header_block_;
-  bool trailing_headers_received_;
+  bool trailing_headers_received_ = false;
 
   // Number of bytes received by the headers stream on behalf of this stream.
-  int64_t headers_bytes_received_;
+  int64_t headers_bytes_received_ = 0;
   // Number of bytes sent by the headers stream on behalf of this stream.
-  int64_t headers_bytes_sent_;
+  int64_t headers_bytes_sent_ = 0;
 
   // Number of bytes received when the stream was closed.
-  int64_t closed_stream_received_bytes_;
+  int64_t closed_stream_received_bytes_ = 0;
   // Number of bytes sent when the stream was closed.
-  int64_t closed_stream_sent_bytes_;
+  int64_t closed_stream_sent_bytes_ = 0;
   // True if the stream is the first stream negotiated on the session. Set when
   // the stream was closed. If |stream_| is failed to be created, this takes on
   // the default value of false.
-  bool closed_is_first_stream_;
+  bool closed_is_first_stream_ = false;
 
   // The caller's callback to be used for asynchronous operations.
   CompletionOnceCallback callback_;
 
   // Caller provided buffer for the ReadResponseBody() response.
   scoped_refptr<IOBuffer> user_buffer_;
-  int user_buffer_len_;
+  int user_buffer_len_ = 0;
 
   // Temporary buffer used to read the request body from UploadDataStream.
   scoped_refptr<IOBufferWithSize> raw_request_body_buf_;
@@ -218,12 +218,13 @@
 
   NetLogWithSource stream_net_log_;
 
-  int session_error_;  // Error code from the connection shutdown.
+  int session_error_ =
+      ERR_UNEXPECTED;  // Error code from the connection shutdown.
 
-  bool found_promise_;
+  bool found_promise_ = false;
 
   // Set to true when DoLoop() is being executed, false otherwise.
-  bool in_loop_;
+  bool in_loop_ = false;
 
   // Session connect timing info.
   LoadTimingInfo::ConnectTiming connect_timing_;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 4313961..a24eb00 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -253,10 +253,7 @@
 class TestSocketPerformanceWatcherFactory
     : public SocketPerformanceWatcherFactory {
  public:
-  TestSocketPerformanceWatcherFactory()
-      : watcher_count_(0u),
-        should_notify_updated_rtt_(true),
-        rtt_notification_received_(false) {}
+  TestSocketPerformanceWatcherFactory() = default;
 
   TestSocketPerformanceWatcherFactory(
       const TestSocketPerformanceWatcherFactory&) = delete;
@@ -287,9 +284,9 @@
   }
 
  private:
-  size_t watcher_count_;
-  bool should_notify_updated_rtt_;
-  bool rtt_notification_received_;
+  size_t watcher_count_ = 0u;
+  bool should_notify_updated_rtt_ = true;
+  bool rtt_notification_received_ = false;
 };
 
 class QuicNetworkTransactionTest
diff --git a/net/quic/quic_proxy_client_socket.cc b/net/quic/quic_proxy_client_socket.cc
index b9c5b0e..512e987 100644
--- a/net/quic/quic_proxy_client_socket.cc
+++ b/net/quic/quic_proxy_client_socket.cc
@@ -31,11 +31,9 @@
     const NetLogWithSource& net_log,
     HttpAuthController* auth_controller,
     ProxyDelegate* proxy_delegate)
-    : next_state_(STATE_DISCONNECTED),
-      stream_(std::move(stream)),
+    : stream_(std::move(stream)),
       session_(std::move(session)),
       read_buf_(nullptr),
-      write_buf_len_(0),
       endpoint_(endpoint),
       auth_(auth_controller),
       proxy_server_(proxy_server),
diff --git a/net/quic/quic_proxy_client_socket.h b/net/quic/quic_proxy_client_socket.h
index 00996b19..4a31834f 100644
--- a/net/quic/quic_proxy_client_socket.h
+++ b/net/quic/quic_proxy_client_socket.h
@@ -107,7 +107,7 @@
   int DoReadReply();
   int DoReadReplyComplete(int result);
 
-  State next_state_;
+  State next_state_ = STATE_DISCONNECTED;
 
   // Handle to the QUIC Stream that this sits on top of.
   std::unique_ptr<QuicChromiumClientStream::Handle> stream_;
@@ -124,7 +124,7 @@
   // Stores the callback for Write().
   CompletionOnceCallback write_callback_;
   // Stores the write buffer length for Write().
-  int write_buf_len_;
+  int write_buf_len_ = 0;
 
   // CONNECT request and response.
   HttpRequestInfo request_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 22108d7..2ed3c62 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -509,7 +509,7 @@
     UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.StaleAndFreshHostMatched", matched);
   }
 
-  IoState io_state_;
+  IoState io_state_ = STATE_RESOLVE_HOST;
   raw_ptr<QuicStreamFactory> factory_;
   quic::ParsedQuicVersion quic_version_;
   raw_ptr<HostResolver> host_resolver_;
@@ -523,9 +523,9 @@
   const bool retry_on_alternate_network_before_handshake_;
   const bool race_stale_dns_on_connection_;
   const NetLogWithSource net_log_;
-  bool host_resolution_finished_;
-  bool connection_retried_;
-  QuicChromiumClientSession* session_;
+  bool host_resolution_finished_ = false;
+  bool connection_retried_ = false;
+  QuicChromiumClientSession* session_ = nullptr;
   // If connection migraiton is supported, |network_| denotes the network on
   // which |session_| is created.
   NetworkChangeNotifier::NetworkHandle network_;
@@ -556,8 +556,7 @@
     bool require_dns_https_alpn,
     int cert_verify_flags,
     const NetLogWithSource& net_log)
-    : io_state_(STATE_RESOLVE_HOST),
-      factory_(factory),
+    : factory_(factory),
       quic_version_(quic_version),
       host_resolver_(host_resolver),
       key_(key),
@@ -574,9 +573,6 @@
       net_log_(
           NetLogWithSource::Make(net_log.net_log(),
                                  NetLogSourceType::QUIC_STREAM_FACTORY_JOB)),
-      host_resolution_finished_(false),
-      connection_retried_(false),
-      session_(nullptr),
       network_(NetworkChangeNotifier::kInvalidNetworkHandle) {
   DCHECK_EQ(quic_version.IsKnown(), !require_dns_https_alpn);
   net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB,
@@ -1033,7 +1029,7 @@
 }
 
 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
-    : factory_(factory), expect_on_host_resolution_(false) {}
+    : factory_(factory) {}
 
 QuicStreamRequest::~QuicStreamRequest() {
   if (factory_ && !callback_.is_null())
@@ -1171,8 +1167,7 @@
     SocketPerformanceWatcherFactory* socket_performance_watcher_factory,
     QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
     QuicContext* quic_context)
-    : is_quic_known_to_work_on_current_network_(false),
-      net_log_(net_log),
+    : net_log_(net_log),
       host_resolver_(host_resolver),
       client_socket_factory_(client_socket_factory),
       http_server_properties_(http_server_properties),
@@ -1201,9 +1196,6 @@
       yield_after_duration_(quic::QuicTime::Delta::FromMilliseconds(
           kQuicYieldAfterDurationMilliseconds)),
       default_network_(NetworkChangeNotifier::kInvalidNetworkHandle),
-      need_to_check_persisted_supports_quic_(true),
-      prefer_aes_gcm_recorded_(false),
-      num_push_streams_created_(0),
       connectivity_monitor_(default_network_),
       tick_clock_(nullptr),
       task_runner_(nullptr),
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 0dad149..7151d302 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -194,7 +194,7 @@
 
   // Set in Request(). If true, then OnHostResolutionComplete() is expected to
   // be called in the future.
-  bool expect_on_host_resolution_;
+  bool expect_on_host_resolution_ = false;
   // Callback passed to WaitForHostResolution().
   CompletionOnceCallback host_resolution_callback_;
 };
@@ -515,7 +515,7 @@
   // expected to work in general, rather than whether QUIC was broken / recently
   // broken when used with a particular server. That information is stored in
   // the broken alternative service map in HttpServerProperties.
-  bool is_quic_known_to_work_on_current_network_;
+  bool is_quic_known_to_work_on_current_network_ = false;
 
   raw_ptr<NetLog> net_log_;
   raw_ptr<HostResolver> host_resolver_;
@@ -599,12 +599,12 @@
   IPEndPoint local_address_;
   // True if we need to check HttpServerProperties if QUIC was supported last
   // time.
-  bool need_to_check_persisted_supports_quic_;
-  bool prefer_aes_gcm_recorded_;
+  bool need_to_check_persisted_supports_quic_ = true;
+  bool prefer_aes_gcm_recorded_ = false;
 
   NetworkConnection network_connection_;
 
-  int num_push_streams_created_;
+  int num_push_streams_created_ = 0;
 
   QuicConnectivityMonitor connectivity_monitor_;
 
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 529b572..32370cf 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -150,7 +150,7 @@
 // IPV4 address.
 class TestConnectionMigrationSocketFactory : public MockClientSocketFactory {
  public:
-  TestConnectionMigrationSocketFactory() : next_source_host_num_(1u) {}
+  TestConnectionMigrationSocketFactory() = default;
 
   TestConnectionMigrationSocketFactory(
       const TestConnectionMigrationSocketFactory&) = delete;
@@ -171,14 +171,14 @@
   }
 
  private:
-  uint8_t next_source_host_num_;
+  uint8_t next_source_host_num_ = 1u;
 };
 
 // TestPortMigrationSocketFactory will vend sockets with incremental port
 // number.
 class TestPortMigrationSocketFactory : public MockClientSocketFactory {
  public:
-  TestPortMigrationSocketFactory() : next_source_port_num_(1u) {}
+  TestPortMigrationSocketFactory() = default;
 
   TestPortMigrationSocketFactory(const TestPortMigrationSocketFactory&) =
       delete;
@@ -199,7 +199,7 @@
   }
 
  private:
-  uint16_t next_source_port_num_;
+  uint16_t next_source_port_num_ = 1u;
 };
 
 class QuicStreamFactoryTestBase : public WithTaskEnvironment {
@@ -238,11 +238,9 @@
         url2_(kServer2Url),
         url3_(kServer3Url),
         url4_(kServer4Url),
-        privacy_mode_(PRIVACY_MODE_DISABLED),
         failed_on_default_network_callback_(base::BindRepeating(
             &QuicStreamFactoryTestBase::OnFailedOnDefaultNetwork,
             base::Unretained(this))),
-        failed_on_default_network_(false),
         quic_params_(context_.params()) {
     FLAGS_quic_enable_http3_grease_randomness = false;
     FLAGS_quic_enable_chaos_protection = false;
@@ -966,11 +964,11 @@
   GURL url3_;
   GURL url4_;
 
-  PrivacyMode privacy_mode_;
+  PrivacyMode privacy_mode_ = PRIVACY_MODE_DISABLED;
   NetLogWithSource net_log_;
   TestCompletionCallback callback_;
   const CompletionRepeatingCallback failed_on_default_network_callback_;
-  bool failed_on_default_network_;
+  bool failed_on_default_network_ = false;
   NetErrorDetails net_error_details_;
 
   raw_ptr<QuicParams> quic_params_;
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc
index 9db4722..374f14b4 100644
--- a/net/quic/quic_test_packet_maker.cc
+++ b/net/quic/quic_test_packet_maker.cc
@@ -108,11 +108,8 @@
       spdy_response_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
       qpack_encoder_(&decoder_stream_error_delegate_),
       perspective_(perspective),
-      encryption_level_(quic::ENCRYPTION_FORWARD_SECURE),
-      long_header_type_(quic::INVALID_PACKET_TYPE),
       client_headers_include_h2_stream_dependency_(
-          client_headers_include_h2_stream_dependency),
-      save_packet_frames_(false) {
+          client_headers_include_h2_stream_dependency) {
   DCHECK(!(perspective_ == quic::Perspective::IS_SERVER &&
            client_headers_include_h2_stream_dependency_));
 
diff --git a/net/quic/quic_test_packet_maker.h b/net/quic/quic_test_packet_maker.h
index bcb5223..f015f9ee 100644
--- a/net/quic/quic_test_packet_maker.h
+++ b/net/quic/quic_test_packet_maker.h
@@ -604,8 +604,8 @@
   quic::test::MockRandom random_generator_;
   std::map<quic::QuicStreamId, quic::QuicStreamOffset> stream_offsets_;
   quic::Perspective perspective_;
-  quic::EncryptionLevel encryption_level_;
-  quic::QuicLongHeaderType long_header_type_;
+  quic::EncryptionLevel encryption_level_ = quic::ENCRYPTION_FORWARD_SECURE;
+  quic::QuicLongHeaderType long_header_type_ = quic::INVALID_PACKET_TYPE;
   // If true, generated request headers will include non-default HTTP2 stream
   // dependency info.
   bool client_headers_include_h2_stream_dependency_;
@@ -614,7 +614,7 @@
   std::vector<std::unique_ptr<std::string>> saved_stream_data_;
   // If |save_packet_frames_| is true, save generated packets in
   // |saved_frames_|, allowing retransmission packets to be built.
-  bool save_packet_frames_;
+  bool save_packet_frames_ = false;
   std::map<quic::QuicPacketNumber, quic::QuicFrames> saved_frames_;
 
   // State necessary for building the current packet.
diff --git a/net/reporting/mock_persistent_reporting_store.cc b/net/reporting/mock_persistent_reporting_store.cc
index 1cb84d0..eed7ef3 100644
--- a/net/reporting/mock_persistent_reporting_store.cc
+++ b/net/reporting/mock_persistent_reporting_store.cc
@@ -153,13 +153,7 @@
   }
 }
 
-MockPersistentReportingStore::MockPersistentReportingStore()
-    : load_started_(false),
-      endpoint_count_(0),
-      endpoint_group_count_(0),
-      queued_endpoint_count_delta_(0),
-      queued_endpoint_group_count_delta_(0) {}
-
+MockPersistentReportingStore::MockPersistentReportingStore() = default;
 MockPersistentReportingStore::~MockPersistentReportingStore() = default;
 
 void MockPersistentReportingStore::LoadReportingClients(
diff --git a/net/reporting/mock_persistent_reporting_store.h b/net/reporting/mock_persistent_reporting_store.h
index a630528..41e06ab 100644
--- a/net/reporting/mock_persistent_reporting_store.h
+++ b/net/reporting/mock_persistent_reporting_store.h
@@ -142,18 +142,18 @@
   std::vector<CachedReportingEndpointGroup> prestored_endpoint_groups_;
 
   // Set when LoadReportingClients() is called.
-  bool load_started_;
+  bool load_started_ = false;
 
   // Simulates the total number of endpoints/groups that would be stored in the
   // store. Updated when pre-stored policies are added, and when Flush() is
   // called.
-  int endpoint_count_;
-  int endpoint_group_count_;
+  int endpoint_count_ = 0;
+  int endpoint_group_count_ = 0;
 
   // Simulates the delta to be added to to the counts the next time Flush() is
   // called. Reset to 0 when Flush() is called.
-  int queued_endpoint_count_delta_;
-  int queued_endpoint_group_count_delta_;
+  int queued_endpoint_count_delta_ = 0;
+  int queued_endpoint_group_count_delta_ = 0;
 };
 
 bool operator==(const MockPersistentReportingStore::Command& lhs,
diff --git a/net/reporting/reporting_cache_unittest.cc b/net/reporting/reporting_cache_unittest.cc
index fd382e6d..d7669ca 100644
--- a/net/reporting/reporting_cache_unittest.cc
+++ b/net/reporting/reporting_cache_unittest.cc
@@ -37,8 +37,7 @@
 
 class TestReportingCacheObserver : public ReportingCacheObserver {
  public:
-  TestReportingCacheObserver()
-      : cached_reports_update_count_(0), cached_clients_update_count_(0) {}
+  TestReportingCacheObserver() = default;
 
   void OnReportsUpdated() override { ++cached_reports_update_count_; }
   void OnClientsUpdated() override { ++cached_clients_update_count_; }
@@ -51,8 +50,8 @@
   }
 
  private:
-  int cached_reports_update_count_;
-  int cached_clients_update_count_;
+  int cached_reports_update_count_ = 0;
+  int cached_clients_update_count_ = 0;
 };
 
 // The tests are parametrized on a boolean value which represents whether or not
diff --git a/net/reporting/reporting_policy.cc b/net/reporting/reporting_policy.cc
index 9756443..956db4137 100644
--- a/net/reporting/reporting_policy.cc
+++ b/net/reporting/reporting_policy.cc
@@ -31,19 +31,11 @@
 }
 
 ReportingPolicy::ReportingPolicy()
-    : max_report_count(100u),
-      max_endpoint_count(1000u),
-      max_endpoints_per_origin(40u),
-      delivery_interval(base::Minutes(1)),
+    : delivery_interval(base::Minutes(1)),
       persistence_interval(base::Minutes(1)),
-      persist_reports_across_restarts(false),
-      persist_clients_across_restarts(true),
       garbage_collection_interval(base::Minutes(5)),
       max_report_age(base::Minutes(15)),
-      max_group_staleness(base::Days(7)),
-      max_report_attempts(5),
-      persist_reports_across_network_changes(false),
-      persist_clients_across_network_changes(true) {
+      max_group_staleness(base::Days(7)) {
   endpoint_backoff_policy.num_errors_to_ignore = 0;
   endpoint_backoff_policy.initial_delay_ms = 60 * 1000;  // 1 minute
   endpoint_backoff_policy.multiply_factor = 2.0;
diff --git a/net/reporting/reporting_policy.h b/net/reporting/reporting_policy.h
index 7dda903..edecae7 100644
--- a/net/reporting/reporting_policy.h
+++ b/net/reporting/reporting_policy.h
@@ -28,15 +28,15 @@
   ~ReportingPolicy();
 
   // Maximum number of reports to queue before evicting the oldest.
-  size_t max_report_count;
+  size_t max_report_count = 100u;
 
   // Maximum number of endpoints to remember before evicting
-  size_t max_endpoint_count;
+  size_t max_endpoint_count = 1000u;
 
   // Maximum number of endpoints for a given origin before evicting
   // TODO(chlily): This is actually a limit on the endpoints for a given client
   // (for a NIK, origin pair), so rename this.
-  size_t max_endpoints_per_origin;
+  size_t max_endpoints_per_origin = 40u;
 
   // Minimum interval at which to attempt delivery of queued reports.
   base::TimeDelta delivery_interval;
@@ -49,11 +49,11 @@
   base::TimeDelta persistence_interval;
 
   // Whether to persist undelivered reports across embedder restarts.
-  bool persist_reports_across_restarts;
+  bool persist_reports_across_restarts = false;
 
   // Whether to persist clients (per-origin endpoint configurations) across
   // embedder restarts.
-  bool persist_clients_across_restarts;
+  bool persist_clients_across_restarts = true;
 
   // Minimum interval at which to garbage-collect the cache.
   base::TimeDelta garbage_collection_interval;
@@ -66,15 +66,15 @@
 
   // Maximum number of delivery attempts a report can have before being
   // discarded as failed.
-  int max_report_attempts;
+  int max_report_attempts = 5;
 
   // Whether to persist (versus clear) reports when the network changes to avoid
   // leaking browsing data between networks.
-  bool persist_reports_across_network_changes;
+  bool persist_reports_across_network_changes = false;
 
   // Whether to persist (versus clear) clients when the network changes to avoid
   // leaking browsing data between networks.
-  bool persist_clients_across_network_changes;
+  bool persist_clients_across_network_changes = true;
 };
 
 }  // namespace net
diff --git a/net/reporting/reporting_service.cc b/net/reporting/reporting_service.cc
index cab6067..02ed98a 100644
--- a/net/reporting/reporting_service.cc
+++ b/net/reporting/reporting_service.cc
@@ -41,11 +41,8 @@
 // Tasks are queued pending completion of loading from the store.
 class ReportingServiceImpl : public ReportingService {
  public:
-  ReportingServiceImpl(std::unique_ptr<ReportingContext> context)
-      : context_(std::move(context)),
-        shut_down_(false),
-        started_loading_from_store_(false),
-        initialized_(false) {
+  explicit ReportingServiceImpl(std::unique_ptr<ReportingContext> context)
+      : context_(std::move(context)) {
     if (!context_->IsClientDataPersisted())
       initialized_ = true;
   }
@@ -301,9 +298,9 @@
   }
 
   std::unique_ptr<ReportingContext> context_;
-  bool shut_down_;
-  bool started_loading_from_store_;
-  bool initialized_;
+  bool shut_down_ = false;
+  bool started_loading_from_store_ = false;
+  bool initialized_ = false;
   std::vector<base::OnceClosure> task_backlog_;
 
   bool respect_network_isolation_key_ = base::FeatureList::IsEnabled(
diff --git a/net/reporting/reporting_uploader.cc b/net/reporting/reporting_uploader.cc
index 75d4bde9..0f978de 100644
--- a/net/reporting/reporting_uploader.cc
+++ b/net/reporting/reporting_uploader.cc
@@ -86,8 +86,7 @@
                 const std::string& json,
                 int max_depth,
                 ReportingUploader::UploadCallback callback)
-      : state(CREATED),
-        report_origin(report_origin),
+      : report_origin(report_origin),
         url(url),
         isolation_info(isolation_info),
         payload_reader(UploadOwnedBytesElementReader::CreateWithString(json)),
@@ -98,7 +97,7 @@
     std::move(callback).Run(outcome);
   }
 
-  State state;
+  State state = CREATED;
   const url::Origin report_origin;
   const GURL url;
   const IsolationInfo isolation_info;
diff --git a/net/reporting/reporting_uploader_unittest.cc b/net/reporting/reporting_uploader_unittest.cc
index add3a94..c414700 100644
--- a/net/reporting/reporting_uploader_unittest.cc
+++ b/net/reporting/reporting_uploader_unittest.cc
@@ -96,7 +96,7 @@
 
 class TestUploadCallback {
  public:
-  TestUploadCallback() : called_(false), waiting_(false) {}
+  TestUploadCallback() = default;
 
   ReportingUploader::UploadCallback callback() {
     return base::BindOnce(&TestUploadCallback::OnUploadComplete,
@@ -129,10 +129,10 @@
     }
   }
 
-  bool called_;
+  bool called_ = false;
   ReportingUploader::Outcome outcome_;
 
-  bool waiting_;
+  bool waiting_ = false;
   base::OnceClosure closure_;
 };
 
diff --git a/net/server/http_connection.cc b/net/server/http_connection.cc
index 0cf5d1a1..73f4fe1bd 100644
--- a/net/server/http_connection.cc
+++ b/net/server/http_connection.cc
@@ -92,9 +92,7 @@
 }
 
 HttpConnection::QueuedWriteIOBuffer::QueuedWriteIOBuffer()
-    : total_size_(0),
-      max_buffer_size_(kDefaultMaxBufferSize) {
-}
+    : max_buffer_size_(kDefaultMaxBufferSize) {}
 
 HttpConnection::QueuedWriteIOBuffer::~QueuedWriteIOBuffer() {
   data_ = nullptr;  // pending_data_ owns data_.
diff --git a/net/server/http_connection.h b/net/server/http_connection.h
index 8f3eaa0d..b59d1b8 100644
--- a/net/server/http_connection.h
+++ b/net/server/http_connection.h
@@ -109,7 +109,7 @@
     // This needs to indirect since we need pointer stability for the payload
     // chunks, as they may be handed out via net::IOBuffer::data().
     base::queue<std::unique_ptr<std::string>> pending_data_;
-    int total_size_;
+    int total_size_ = 0;
     int max_buffer_size_;
   };
 
diff --git a/net/server/http_server.cc b/net/server/http_server.cc
index 909ed5c..b9a556e 100644
--- a/net/server/http_server.cc
+++ b/net/server/http_server.cc
@@ -54,9 +54,7 @@
 
 HttpServer::HttpServer(std::unique_ptr<ServerSocket> server_socket,
                        HttpServer::Delegate* delegate)
-    : server_socket_(std::move(server_socket)),
-      delegate_(delegate),
-      last_id_(0) {
+    : server_socket_(std::move(server_socket)), delegate_(delegate) {
   DCHECK(server_socket_);
   // Start accepting connections in next run loop in case when delegate is not
   // ready to get callbacks.
diff --git a/net/server/http_server.h b/net/server/http_server.h
index 7ca9406..30f1735 100644
--- a/net/server/http_server.h
+++ b/net/server/http_server.h
@@ -132,7 +132,7 @@
   std::unique_ptr<StreamSocket> accepted_socket_;
   const raw_ptr<HttpServer::Delegate> delegate_;
 
-  int last_id_;
+  int last_id_ = 0;
   std::map<int, std::unique_ptr<HttpConnection>> id_to_connection_;
 
   base::WeakPtrFactory<HttpServer> weak_ptr_factory_{this};
diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc
index 72fccea1..ea67618e 100644
--- a/net/server/http_server_unittest.cc
+++ b/net/server/http_server_unittest.cc
@@ -178,7 +178,7 @@
 class HttpServerTest : public TestWithTaskEnvironment,
                        public HttpServer::Delegate {
  public:
-  HttpServerTest() : quit_on_close_connection_(-1) {}
+  HttpServerTest() = default;
 
   void SetUp() override {
     std::unique_ptr<ServerSocket> server_socket(
@@ -276,7 +276,7 @@
  private:
   base::test::RepeatingTestFuture<ReceivedRequest> received_requests_;
   std::unique_ptr<base::RunLoop> quit_on_create_loop_;
-  int quit_on_close_connection_;
+  int quit_on_close_connection_ = -1;
 };
 
 namespace {
@@ -943,7 +943,7 @@
 
 class MockStreamSocket : public StreamSocket {
  public:
-  MockStreamSocket() : connected_(true), read_buf_(nullptr), read_buf_len_(0) {}
+  MockStreamSocket() : read_buf_(nullptr) {}
 
   MockStreamSocket(const MockStreamSocket&) = delete;
   MockStreamSocket& operator=(const MockStreamSocket&) = delete;
@@ -1027,9 +1027,9 @@
  private:
   ~MockStreamSocket() override = default;
 
-  bool connected_;
+  bool connected_ = true;
   scoped_refptr<IOBuffer> read_buf_;
-  int read_buf_len_;
+  int read_buf_len_ = 0;
   CompletionOnceCallback read_callback_;
   std::string pending_read_data_;
   NetLogWithSource net_log_;
diff --git a/net/server/web_socket.cc b/net/server/web_socket.cc
index 6046222..c4155cb7 100644
--- a/net/server/web_socket.cc
+++ b/net/server/web_socket.cc
@@ -52,7 +52,7 @@
 }  // namespace
 
 WebSocket::WebSocket(HttpServer* server, HttpConnection* connection)
-    : server_(server), connection_(connection), closed_(false) {}
+    : server_(server), connection_(connection) {}
 
 WebSocket::~WebSocket() = default;
 
diff --git a/net/server/web_socket.h b/net/server/web_socket.h
index af27eb6..ce53804e6 100644
--- a/net/server/web_socket.h
+++ b/net/server/web_socket.h
@@ -56,7 +56,7 @@
   const raw_ptr<HttpServer> server_;
   const raw_ptr<HttpConnection> connection_;
   std::unique_ptr<WebSocketEncoder> encoder_;
-  bool closed_;
+  bool closed_ = false;
   std::unique_ptr<NetworkTrafficAnnotationTag> traffic_annotation_ = nullptr;
 };
 
diff --git a/net/socket/client_socket_handle.cc b/net/socket/client_socket_handle.cc
index 8de84106..a51fea51 100644
--- a/net/socket/client_socket_handle.cc
+++ b/net/socket/client_socket_handle.cc
@@ -21,13 +21,9 @@
 namespace net {
 
 ClientSocketHandle::ClientSocketHandle()
-    : is_initialized_(false),
-      pool_(nullptr),
+    : pool_(nullptr),
       higher_pool_(nullptr),
-      reuse_type_(ClientSocketHandle::UNUSED),
-      group_generation_(-1),
-      resolve_error_info_(ResolveErrorInfo(OK)),
-      is_ssl_error_(false) {}
+      resolve_error_info_(ResolveErrorInfo(OK)) {}
 
 ClientSocketHandle::~ClientSocketHandle() {
   Reset();
diff --git a/net/socket/client_socket_handle.h b/net/socket/client_socket_handle.h
index 48dd94f..6f68a98 100644
--- a/net/socket/client_socket_handle.h
+++ b/net/socket/client_socket_handle.h
@@ -228,18 +228,18 @@
   // Resets the supplemental error state.
   void ResetErrorState();
 
-  bool is_initialized_;
+  bool is_initialized_ = false;
   raw_ptr<ClientSocketPool> pool_;
   raw_ptr<HigherLayeredPool> higher_pool_;
   std::unique_ptr<StreamSocket> socket_;
   ClientSocketPool::GroupId group_id_;
-  SocketReuseType reuse_type_;
+  SocketReuseType reuse_type_ = ClientSocketHandle::UNUSED;
   CompletionOnceCallback callback_;
   base::TimeDelta idle_time_;
   // See ClientSocketPool::ReleaseSocket() for an explanation.
-  int64_t group_generation_;
+  int64_t group_generation_ = -1;
   ResolveErrorInfo resolve_error_info_;
-  bool is_ssl_error_;
+  bool is_ssl_error_ = false;
   scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;
   std::vector<ConnectionAttempt> connection_attempts_;
 
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index ae102ac..c5dded33 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -148,10 +148,7 @@
 class MockClientSocket : public StreamSocket {
  public:
   explicit MockClientSocket(net::NetLog* net_log)
-      : connected_(false),
-        has_unread_data_(false),
-        net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)),
-        was_used_to_convey_data_(false) {}
+      : net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {}
 
   MockClientSocket(const MockClientSocket&) = delete;
   MockClientSocket& operator=(const MockClientSocket&) = delete;
@@ -218,17 +215,17 @@
   void ApplySocketTag(const SocketTag& tag) override {}
 
  private:
-  bool connected_;
-  bool has_unread_data_;
+  bool connected_ = false;
+  bool has_unread_data_ = false;
   NetLogWithSource net_log_;
-  bool was_used_to_convey_data_;
+  bool was_used_to_convey_data_ = false;
 };
 
 class TestConnectJob;
 
 class MockClientSocketFactory : public ClientSocketFactory {
  public:
-  MockClientSocketFactory() : allocation_count_(0) {}
+  MockClientSocketFactory() = default;
 
   std::unique_ptr<DatagramClientSocket> CreateDatagramClientSocket(
       DatagramSocket::BindType bind_type,
@@ -273,7 +270,7 @@
   int allocation_count() const { return allocation_count_; }
 
  private:
-  int allocation_count_;
+  int allocation_count_ = 0;
   std::vector<TestConnectJob*> waiting_jobs_;
 };
 
@@ -320,10 +317,7 @@
                    NetLogSourceType::TRANSPORT_CONNECT_JOB,
                    NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
         job_type_(job_type),
-        client_socket_factory_(client_socket_factory),
-        load_state_(LOAD_STATE_IDLE),
-        has_established_connection_(false),
-        store_additional_error_state_(false) {}
+        client_socket_factory_(client_socket_factory) {}
 
   TestConnectJob(const TestConnectJob&) = delete;
   TestConnectJob& operator=(const TestConnectJob&) = delete;
@@ -517,9 +511,9 @@
   bool waiting_success_;
   const JobType job_type_;
   const raw_ptr<MockClientSocketFactory> client_socket_factory_;
-  LoadState load_state_;
-  bool has_established_connection_;
-  bool store_additional_error_state_;
+  LoadState load_state_ = LOAD_STATE_IDLE;
+  bool has_established_connection_ = false;
+  bool store_additional_error_state_ = false;
 
   base::WeakPtrFactory<TestConnectJob> weak_factory_{this};
 };
@@ -4860,7 +4854,7 @@
  public:
   MockLayeredPool(TransportClientSocketPool* pool,
                   const ClientSocketPool::GroupId& group_id)
-      : pool_(pool), group_id_(group_id), can_release_connection_(true) {
+      : pool_(pool), group_id_(group_id) {
     pool_->AddHigherLayeredPool(this);
   }
 
@@ -4902,7 +4896,7 @@
   ClientSocketHandle handle_;
   TestCompletionCallback callback_;
   const ClientSocketPool::GroupId group_id_;
-  bool can_release_connection_;
+  bool can_release_connection_ = true;
 };
 
 // Tests the basic case of closing an idle socket in a higher layered pool when
diff --git a/net/socket/connect_job_unittest.cc b/net/socket/connect_job_unittest.cc
index 39a1329..8e8918b 100644
--- a/net/socket/connect_job_unittest.cc
+++ b/net/socket/connect_job_unittest.cc
@@ -43,8 +43,7 @@
                    nullptr /* net_log */,
                    NetLogSourceType::TRANSPORT_CONNECT_JOB,
                    NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
-        job_type_(job_type),
-        last_seen_priority_(DEFAULT_PRIORITY) {
+        job_type_(job_type) {
     switch (job_type_) {
       case JobType::kSyncSuccess:
         socket_data_provider_.set_connect_data(MockConnect(SYNCHRONOUS, OK));
@@ -87,7 +86,7 @@
  protected:
   const JobType job_type_;
   StaticSocketDataProvider socket_data_provider_;
-  RequestPriority last_seen_priority_;
+  RequestPriority last_seen_priority_ = DEFAULT_PRIORITY;
 };
 
 class ConnectJobTest : public testing::Test {
diff --git a/net/socket/sequenced_socket_data_unittest.cc b/net/socket/sequenced_socket_data_unittest.cc
index b8905f3..41843e8 100644
--- a/net/socket/sequenced_socket_data_unittest.cc
+++ b/net/socket/sequenced_socket_data_unittest.cc
@@ -47,14 +47,7 @@
 // a read or write operation specified by SetInvokeRead or SetInvokeWrite.
 class ReentrantHelper {
  public:
-  ReentrantHelper(StreamSocket* socket)
-      : socket_(socket),
-        verify_read_(false),
-        first_read_data_(nullptr),
-        first_len_(-1),
-        second_read_(false),
-        second_write_data_(nullptr),
-        second_len_(-1) {}
+  explicit ReentrantHelper(StreamSocket* socket) : socket_(socket) {}
 
   ReentrantHelper(const ReentrantHelper&) = delete;
   ReentrantHelper& operator=(const ReentrantHelper&) = delete;
@@ -135,17 +128,17 @@
 
   raw_ptr<StreamSocket> socket_;
 
-  bool verify_read_;
+  bool verify_read_ = false;
   scoped_refptr<IOBuffer> first_read_buf_;
-  const char* first_read_data_;
-  int first_len_;
+  const char* first_read_data_ = nullptr;
+  int first_len_ = -1;
 
   CompletionOnceCallback second_callback_;
-  bool second_read_;
+  bool second_read_ = false;
   int second_rv_;
   scoped_refptr<IOBuffer> second_read_buf_;
-  const char* second_write_data_;
-  int second_len_;
+  const char* second_write_data_ = nullptr;
+  int second_len_ = -1;
 };
 
 class SequencedSocketDataTest : public TestWithTaskEnvironment {
@@ -227,12 +220,12 @@
   std::unique_ptr<SequencedSocketData> data_;
 
   MockClientSocketFactory socket_factory_;
-  bool expect_eof_;
+  bool expect_eof_ = true;
 
   std::unique_ptr<StreamSocket> sock_;
 };
 
-SequencedSocketDataTest::SequencedSocketDataTest() : expect_eof_(true) {}
+SequencedSocketDataTest::SequencedSocketDataTest() = default;
 
 SequencedSocketDataTest::~SequencedSocketDataTest() {
   // Make sure no unexpected pending tasks will cause a failure.
diff --git a/net/socket/socket_bio_adapter.cc b/net/socket/socket_bio_adapter.cc
index 8ff8c58..38423545 100644
--- a/net/socket/socket_bio_adapter.cc
+++ b/net/socket/socket_bio_adapter.cc
@@ -62,11 +62,7 @@
                                    Delegate* delegate)
     : socket_(socket),
       read_buffer_capacity_(read_buffer_capacity),
-      read_offset_(0),
-      read_result_(0),
       write_buffer_capacity_(write_buffer_capacity),
-      write_buffer_used_(0),
-      write_error_(OK),
       delegate_(delegate) {
   bio_.reset(BIO_new(&kBIOMethod));
   bio_->ptr = this;
diff --git a/net/socket/socket_bio_adapter.h b/net/socket/socket_bio_adapter.h
index f5fed240..487e9b7e 100644
--- a/net/socket/socket_bio_adapter.h
+++ b/net/socket/socket_bio_adapter.h
@@ -9,6 +9,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "net/base/completion_repeating_callback.h"
+#include "net/base/net_errors.h"
 #include "net/base/net_export.h"
 #include "third_party/boringssl/src/include/openssl/base.h"
 
@@ -120,11 +121,11 @@
   // deallocated when unused.
   scoped_refptr<IOBuffer> read_buffer_;
   // The number of bytes of read_buffer_ consumed.
-  int read_offset_;
+  int read_offset_ = 0;
   // The result of the most recent socket Read(). If ERR_IO_PENDING, there is a
   // socket Read() in progress. If another error, Read() has failed. Otherwise,
   // it is the number of bytes in the buffer (zero if empty).
-  int read_result_;
+  int read_result_ = 0;
 
   // The capacity of the write buffer.
   int write_buffer_capacity_;
@@ -133,11 +134,11 @@
   // Write(). The buffer is deallocated when unused.
   scoped_refptr<GrowableIOBuffer> write_buffer_;
   // The number of bytes of data in write_buffer_.
-  int write_buffer_used_;
+  int write_buffer_used_ = 0;
   // The most recent socket Write() error. If ERR_IO_PENDING, there is a socket
   // Write() in progress. If OK, there is no socket Write() in progress and none
   // have failed.
-  int write_error_;
+  int write_error_ = OK;
 
   raw_ptr<Delegate> delegate_;
 
diff --git a/net/socket/socket_posix.cc b/net/socket/socket_posix.cc
index c3b6eb06..1e054bd7 100644
--- a/net/socket/socket_posix.cc
+++ b/net/socket/socket_posix.cc
@@ -72,10 +72,7 @@
     : socket_fd_(kInvalidSocket),
       accept_socket_watcher_(FROM_HERE),
       read_socket_watcher_(FROM_HERE),
-      read_buf_len_(0),
-      write_socket_watcher_(FROM_HERE),
-      write_buf_len_(0),
-      waiting_connect_(false) {}
+      write_socket_watcher_(FROM_HERE) {}
 
 SocketPosix::~SocketPosix() {
   Close();
diff --git a/net/socket/socket_posix.h b/net/socket/socket_posix.h
index 29b0209..02d1600 100644
--- a/net/socket/socket_posix.h
+++ b/net/socket/socket_posix.h
@@ -137,7 +137,7 @@
 
   // Non-null when a Read() is in progress.
   scoped_refptr<IOBuffer> read_buf_;
-  int read_buf_len_;
+  int read_buf_len_ = 0;
   CompletionOnceCallback read_callback_;
 
   // Non-null when a ReadIfReady() is in progress.
@@ -145,13 +145,13 @@
 
   base::MessagePumpForIO::FdWatchController write_socket_watcher_;
   scoped_refptr<IOBuffer> write_buf_;
-  int write_buf_len_;
+  int write_buf_len_ = 0;
   // External callback; called when write or connect is complete.
   CompletionOnceCallback write_callback_;
 
   // A connect operation is pending. In this case, |write_callback_| needs to be
   // called when connect is complete.
-  bool waiting_connect_;
+  bool waiting_connect_ = false;
 
   std::unique_ptr<SockaddrStorage> peer_address_;
 
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 028a6a7b..f9f41402 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -187,7 +187,7 @@
 StaticSocketDataHelper::StaticSocketDataHelper(
     base::span<const MockRead> reads,
     base::span<const MockWrite> writes)
-    : reads_(reads), read_index_(0), writes_(writes), write_index_(0) {}
+    : reads_(reads), writes_(writes) {}
 
 StaticSocketDataHelper::~StaticSocketDataHelper() = default;
 
@@ -334,8 +334,6 @@
 
 SSLSocketDataProvider::SSLSocketDataProvider(IoMode mode, int result)
     : connect(mode, result),
-      next_proto(kProtoUnknown),
-      cert_request_info(nullptr),
       expected_ssl_version_min(kDefaultSSLVersionMin),
       expected_ssl_version_max(kDefaultSSLVersionMax) {
   SSLConnectionStatusSetVersion(SSL_CONNECTION_VERSION_TLS1_3,
@@ -743,8 +741,7 @@
 
 SequencedSocketData::~SequencedSocketData() = default;
 
-MockClientSocketFactory::MockClientSocketFactory()
-    : enable_read_if_ready_(false) {}
+MockClientSocketFactory::MockClientSocketFactory() = default;
 
 MockClientSocketFactory::~MockClientSocketFactory() = default;
 
@@ -859,7 +856,7 @@
 }
 
 MockClientSocket::MockClientSocket(const NetLogWithSource& net_log)
-    : connected_(false), net_log_(net_log) {
+    : net_log_(net_log) {
   local_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 123);
   peer_addr_ = IPEndPoint(IPAddress(192, 0, 2, 33), 0);
 }
@@ -942,14 +939,8 @@
     : MockClientSocket(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)),
       addresses_(addresses),
       data_(data),
-      read_offset_(0),
       read_data_(SYNCHRONOUS, ERR_UNEXPECTED),
-      need_read_data_(true),
-      peer_closed_connection_(false),
-      pending_read_buf_(nullptr),
-      pending_read_buf_len_(0),
-      was_used_to_convey_data_(false),
-      enable_read_if_ready_(false) {
+      pending_read_buf_(nullptr) {
   DCHECK(data_);
   peer_addr_ = data->connect_data().peer_addr;
   data_->Initialize(this);
@@ -1510,16 +1501,11 @@
 
 MockUDPClientSocket::MockUDPClientSocket(SocketDataProvider* data,
                                          net::NetLog* net_log)
-    : connected_(false),
-      data_(data),
-      read_offset_(0),
+    : data_(data),
       read_data_(SYNCHRONOUS, ERR_UNEXPECTED),
-      need_read_data_(true),
       source_host_(IPAddress(192, 0, 2, 33)),
-      source_port_(123),
       network_(NetworkChangeNotifier::kInvalidNetworkHandle),
       pending_read_buf_(nullptr),
-      pending_read_buf_len_(0),
       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::NONE)) {
   if (data_) {
     data_->Initialize(this);
@@ -1868,7 +1854,7 @@
 // static
 const int ClientSocketPoolTest::kRequestNotFound = -2;
 
-ClientSocketPoolTest::ClientSocketPoolTest() : completion_count_(0) {}
+ClientSocketPoolTest::ClientSocketPoolTest() = default;
 ClientSocketPoolTest::~ClientSocketPoolTest() = default;
 
 int ClientSocketPoolTest::GetOrderOfRequest(size_t index) const {
@@ -1980,10 +1966,8 @@
           ProxyServer::Direct(),
           false /* is_for_websockets */,
           common_connect_job_params),
-      client_socket_factory_(common_connect_job_params->client_socket_factory),
-      last_request_priority_(DEFAULT_PRIORITY),
-      release_count_(0),
-      cancel_count_(0) {}
+      client_socket_factory_(common_connect_job_params->client_socket_factory) {
+}
 
 MockTransportClientSocketPool::~MockTransportClientSocketPool() = default;
 
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 147b03a..788df9d 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -409,9 +409,9 @@
   const MockWrite& PeekRealWrite() const;
 
   const base::span<const MockRead> reads_;
-  size_t read_index_;
+  size_t read_index_ = 0;
   const base::span<const MockWrite> writes_;
-  size_t write_index_;
+  size_t write_index_ = 0;
 };
 
 // SocketDataProvider which responds based on static tables of mock reads and
@@ -483,7 +483,7 @@
   base::RepeatingClosure confirm_callback;
 
   // Result for GetNegotiatedProtocol().
-  NextProto next_proto;
+  NextProto next_proto = kProtoUnknown;
 
   // Result for GetPeerApplicationSettings().
   absl::optional<std::string> peer_application_settings;
@@ -492,7 +492,7 @@
   SSLInfo ssl_info;
 
   // Result for GetSSLCertRequestInfo().
-  SSLCertRequestInfo* cert_request_info;
+  SSLCertRequestInfo* cert_request_info = nullptr;
 
   // Result for GetECHRetryConfigs().
   std::vector<uint8_t> ech_retry_configs;
@@ -713,7 +713,7 @@
 
   // If true, ReadIfReady() is enabled; otherwise ReadIfReady() returns
   // ERR_READ_IF_READY_NOT_IMPLEMENTED.
-  bool enable_read_if_ready_;
+  bool enable_read_if_ready_ = false;
 };
 
 class MockClientSocket : public TransportClientSocket {
@@ -761,7 +761,7 @@
   void RunCallback(CompletionOnceCallback callback, int result);
 
   // True if Connect completed successfully and Disconnect hasn't been called.
-  bool connected_;
+  bool connected_ = false;
 
   IPEndPoint local_addr_;
   IPEndPoint peer_addr_;
@@ -837,18 +837,18 @@
   AddressList addresses_;
 
   raw_ptr<SocketDataProvider> data_;
-  int read_offset_;
+  int read_offset_ = 0;
   MockRead read_data_;
-  bool need_read_data_;
+  bool need_read_data_ = true;
 
   // True if the peer has closed the connection.  This allows us to simulate
   // the recv(..., MSG_PEEK) call in the IsConnectedAndIdle method of the real
   // TCPClientSocket.
-  bool peer_closed_connection_;
+  bool peer_closed_connection_ = false;
 
   // While an asynchronous read is pending, we save our user-buffer state.
   scoped_refptr<IOBuffer> pending_read_buf_;
-  int pending_read_buf_len_;
+  int pending_read_buf_len_ = 0;
   CompletionOnceCallback pending_read_callback_;
 
   // Non-null when a ReadIfReady() is pending.
@@ -856,11 +856,11 @@
 
   CompletionOnceCallback pending_connect_callback_;
   CompletionOnceCallback pending_write_callback_;
-  bool was_used_to_convey_data_;
+  bool was_used_to_convey_data_ = false;
 
   // If true, ReadIfReady() is enabled; otherwise ReadIfReady() returns
   // ERR_READ_IF_READY_NOT_IMPLEMENTED.
-  bool enable_read_if_ready_;
+  bool enable_read_if_ready_ = false;
 
   BeforeConnectCallback before_connect_callback_;
 };
@@ -1033,13 +1033,13 @@
   void RunCallbackAsync(CompletionOnceCallback callback, int result);
   void RunCallback(CompletionOnceCallback callback, int result);
 
-  bool connected_;
+  bool connected_ = false;
   raw_ptr<SocketDataProvider> data_;
-  int read_offset_;
+  int read_offset_ = 0;
   MockRead read_data_;
-  bool need_read_data_;
+  bool need_read_data_ = true;
   IPAddress source_host_;
-  uint16_t source_port_;  // Ephemeral source port.
+  uint16_t source_port_ = 123;  // Ephemeral source port.
 
   // Address of the "remote" peer we're connected to.
   IPEndPoint peer_addr_;
@@ -1049,7 +1049,7 @@
 
   // While an asynchronous IO is pending, we save our user-buffer state.
   scoped_refptr<IOBuffer> pending_read_buf_;
-  int pending_read_buf_len_;
+  int pending_read_buf_len_ = 0;
   CompletionOnceCallback pending_read_callback_;
   CompletionOnceCallback pending_write_callback_;
 
@@ -1154,7 +1154,7 @@
  private:
   std::vector<std::unique_ptr<TestSocketRequest>> requests_;
   std::vector<TestSocketRequest*> request_order_;
-  size_t completion_count_;
+  size_t completion_count_ = 0;
 };
 
 class MockTransportSocketParams
@@ -1249,9 +1249,9 @@
  private:
   raw_ptr<ClientSocketFactory> client_socket_factory_;
   std::vector<std::unique_ptr<MockConnectJob>> job_list_;
-  RequestPriority last_request_priority_;
-  int release_count_;
-  int cancel_count_;
+  RequestPriority last_request_priority_ = DEFAULT_PRIORITY;
+  int release_count_ = 0;
+  int cancel_count_ = 0;
 };
 
 // WrappedStreamSocket is a base class that wraps an existing StreamSocket,
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index dce65101..cc8dd8a0 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -38,12 +38,7 @@
     : io_callback_(base::BindRepeating(&SOCKS5ClientSocket::OnIOComplete,
                                        base::Unretained(this))),
       transport_socket_(std::move(transport_socket)),
-      next_state_(STATE_NONE),
-      completed_handshake_(false),
-      bytes_sent_(0),
-      bytes_received_(0),
       read_header_size(kReadHeaderSize),
-      was_ever_used_(false),
       destination_(destination),
       net_log_(transport_socket_->NetLog()),
       traffic_annotation_(traffic_annotation) {}
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index 41b58b6..5612be0 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -125,7 +125,7 @@
   // Stores the underlying socket.
   std::unique_ptr<StreamSocket> transport_socket_;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   // Stores the callback to the layer above, called on completing Connect().
   CompletionOnceCallback user_callback_;
@@ -141,15 +141,15 @@
 
   // This becomes true when the SOCKS handshake has completed and the
   // overlying connection is free to communicate.
-  bool completed_handshake_;
+  bool completed_handshake_ = false;
 
   // These contain the bytes sent / received by the SOCKS handshake.
-  size_t bytes_sent_;
-  size_t bytes_received_;
+  size_t bytes_sent_ = 0;
+  size_t bytes_received_ = 0;
 
   size_t read_header_size;
 
-  bool was_ever_used_;
+  bool was_ever_used_ = false;
 
   const HostPortPair destination_;
 
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index 782e4822..a6887260 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -68,11 +68,6 @@
     SecureDnsPolicy secure_dns_policy,
     const NetworkTrafficAnnotationTag& traffic_annotation)
     : transport_socket_(std::move(transport_socket)),
-      next_state_(STATE_NONE),
-      completed_handshake_(false),
-      bytes_sent_(0),
-      bytes_received_(0),
-      was_ever_used_(false),
       host_resolver_(host_resolver),
       secure_dns_policy_(secure_dns_policy),
       destination_(destination),
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index d053827b..1f30a219 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -117,7 +117,7 @@
   // Stores the underlying socket.
   std::unique_ptr<StreamSocket> transport_socket_;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   // Stores the callbacks to the layer above, called on completing Connect().
   CompletionOnceCallback user_callback_;
@@ -133,14 +133,14 @@
 
   // This becomes true when the SOCKS handshake has completed and the
   // overlying connection is free to communicate.
-  bool completed_handshake_;
+  bool completed_handshake_ = false;
 
   // These contain the bytes sent / received by the SOCKS handshake.
-  size_t bytes_sent_;
-  size_t bytes_received_;
+  size_t bytes_sent_ = 0;
+  size_t bytes_received_ = 0;
 
   // This becomes true when the socket is used to send or receive data.
-  bool was_ever_used_;
+  bool was_ever_used_ = false;
 
   // Used to resolve the hostname to which the SOCKS proxy will connect.
   raw_ptr<HostResolver> host_resolver_;
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index 0e86859..08bfe951 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -15,9 +15,7 @@
 
 namespace net {
 
-SSLClientSocket::SSLClientSocket()
-    : signed_cert_timestamps_received_(false),
-      stapled_ocsp_response_received_(false) {}
+SSLClientSocket::SSLClientSocket() = default;
 
 // static
 void SSLClientSocket::SetSSLKeyLogger(std::unique_ptr<SSLKeyLogger> logger) {
diff --git a/net/socket/ssl_client_socket.h b/net/socket/ssl_client_socket.h
index a49095c..35ca217 100644
--- a/net/socket/ssl_client_socket.h
+++ b/net/socket/ssl_client_socket.h
@@ -80,9 +80,9 @@
                            ConnectSignedCertTimestampsEnablesOCSP);
 
   // True if SCTs were received via a TLS extension.
-  bool signed_cert_timestamps_received_;
+  bool signed_cert_timestamps_received_ = false;
   // True if a stapled OCSP response was received.
-  bool stapled_ocsp_response_received_;
+  bool stapled_ocsp_response_received_ = false;
 };
 
 // Shared state and configuration across multiple SSLClientSockets.
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc
index 9943a21e..fd2171c 100644
--- a/net/socket/ssl_client_socket_impl.cc
+++ b/net/socket/ssl_client_socket_impl.cc
@@ -382,23 +382,12 @@
     const HostPortPair& host_and_port,
     const SSLConfig& ssl_config)
     : pending_read_error_(kSSLClientSocketNoPendingResult),
-      pending_read_ssl_error_(SSL_ERROR_NONE),
-      completed_connect_(false),
-      was_ever_used_(false),
       context_(context),
       cert_verification_result_(kCertVerifyPending),
       stream_socket_(std::move(stream_socket)),
       host_and_port_(host_and_port),
       ssl_config_(ssl_config),
-      next_handshake_state_(STATE_NONE),
-      in_confirm_handshake_(false),
-      peek_complete_(false),
-      disconnected_(false),
-      negotiated_protocol_(kProtoUnknown),
-      certificate_requested_(false),
       signature_result_(kSSLClientSocketNoPendingResult),
-      pkp_bypassed_(false),
-      is_fatal_cert_error_(false),
       net_log_(stream_socket_->NetLog()) {
   CHECK(context_);
 }
diff --git a/net/socket/ssl_client_socket_impl.h b/net/socket/ssl_client_socket_impl.h
index deed27f..e8c93487 100644
--- a/net/socket/ssl_client_socket_impl.h
+++ b/net/socket/ssl_client_socket_impl.h
@@ -239,7 +239,7 @@
 
   // If there is a pending read result, the OpenSSL result code (output of
   // SSL_get_error) associated with it.
-  int pending_read_ssl_error_;
+  int pending_read_ssl_error_ = SSL_ERROR_NONE;
 
   // If there is a pending read result, the OpenSSLErrorInfo associated with it.
   OpenSSLErrorInfo pending_read_error_info_;
@@ -247,11 +247,11 @@
   // Set when Connect finishes.
   scoped_refptr<X509Certificate> server_cert_;
   CertVerifyResult server_cert_verify_result_;
-  bool completed_connect_;
+  bool completed_connect_ = false;
 
   // Set when Read() or Write() successfully reads or writes data to or from the
   // network.
-  bool was_ever_used_;
+  bool was_ever_used_ = false;
 
   const raw_ptr<SSLClientContext> context_;
 
@@ -274,24 +274,24 @@
     STATE_HANDSHAKE,
     STATE_HANDSHAKE_COMPLETE,
   };
-  State next_handshake_state_;
+  State next_handshake_state_ = STATE_NONE;
 
   // True if we are currently confirming the handshake.
-  bool in_confirm_handshake_;
+  bool in_confirm_handshake_ = false;
 
   // True if the post-handshake SSL_peek has completed.
-  bool peek_complete_;
+  bool peek_complete_ = false;
 
   // True if the socket has been disconnected.
-  bool disconnected_;
+  bool disconnected_ = false;
 
   // True if certificate verification used an ECH name override.
   bool used_ech_name_override_ = false;
 
-  NextProto negotiated_protocol_;
+  NextProto negotiated_protocol_ = kProtoUnknown;
 
   // Set to true if a CertificateRequest was received.
-  bool certificate_requested_;
+  bool certificate_requested_ = false;
 
   int signature_result_;
   std::vector<uint8_t> signature_;
@@ -302,11 +302,11 @@
   std::string pinning_failure_log_;
 
   // True if PKP is bypassed due to a local trust anchor.
-  bool pkp_bypassed_;
+  bool pkp_bypassed_ = false;
 
   // True if there was a certificate error which should be treated as fatal,
   // and false otherwise.
-  bool is_fatal_cert_error_;
+  bool is_fatal_cert_error_ = false;
 
   // True if the socket should respond to client certificate requests with
   // |client_cert_| and |client_private_key_|, which may be null to continue
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc
index ffbb0cc1..a01a153 100644
--- a/net/socket/ssl_client_socket_unittest.cc
+++ b/net/socket/ssl_client_socket_unittest.cc
@@ -531,9 +531,7 @@
 class CountingStreamSocket : public WrappedStreamSocket {
  public:
   explicit CountingStreamSocket(std::unique_ptr<StreamSocket> transport)
-      : WrappedStreamSocket(std::move(transport)),
-        read_count_(0),
-        write_count_(0) {}
+      : WrappedStreamSocket(std::move(transport)) {}
   ~CountingStreamSocket() override = default;
 
   // Socket implementation:
@@ -556,8 +554,8 @@
   int write_count() const { return write_count_; }
 
  private:
-  int read_count_;
-  int write_count_;
+  int read_count_ = 0;
+  int write_count_ = 0;
 };
 
 // A helper class that will delete |socket| when the callback is invoked.
@@ -593,7 +591,7 @@
 // reported and the number of violations reported.
 class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
  public:
-  MockExpectCTReporter() : num_failures_(0) {}
+  MockExpectCTReporter() = default;
   ~MockExpectCTReporter() override = default;
 
   void OnExpectCTFailed(
@@ -634,7 +632,7 @@
  private:
   HostPortPair host_port_pair_;
   GURL report_uri_;
-  uint32_t num_failures_;
+  uint32_t num_failures_ = 0;
   raw_ptr<const X509Certificate> served_certificate_chain_;
   raw_ptr<const X509Certificate> validated_certificate_chain_;
   SignedCertificateTimestampAndStatusList signed_certificate_timestamps_;
diff --git a/net/socket/ssl_connect_job.cc b/net/socket/ssl_connect_job.cc
index af1a435..6646027 100644
--- a/net/socket/ssl_connect_job.cc
+++ b/net/socket/ssl_connect_job.cc
@@ -134,9 +134,7 @@
           NetLogEventType::SSL_CONNECT_JOB_CONNECT),
       params_(std::move(params)),
       callback_(base::BindRepeating(&SSLConnectJob::OnIOComplete,
-                                    base::Unretained(this))),
-      ssl_negotiation_started_(false),
-      disable_legacy_crypto_with_fallback_(true) {}
+                                    base::Unretained(this))) {}
 
 SSLConnectJob::~SSLConnectJob() {
   // In the case the job was canceled, need to delete nested job first to
diff --git a/net/socket/ssl_connect_job.h b/net/socket/ssl_connect_job.h
index 66b9d0f..7d4c3c21 100644
--- a/net/socket/ssl_connect_job.h
+++ b/net/socket/ssl_connect_job.h
@@ -188,12 +188,12 @@
   std::unique_ptr<SSLClientSocket> ssl_socket_;
 
   // True once SSL negotiation has started.
-  bool ssl_negotiation_started_;
+  bool ssl_negotiation_started_ = false;
 
   // True if legacy crypto should be disabled for the job's current connection
   // attempt. On error, the connection will be retried with legacy crypto
   // enabled.
-  bool disable_legacy_crypto_with_fallback_;
+  bool disable_legacy_crypto_with_fallback_ = true;
 
   scoped_refptr<SSLCertRequestInfo> ssl_cert_request_info_;
 
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc
index 1e2a9f4..5b6598c 100644
--- a/net/socket/ssl_server_socket_impl.cc
+++ b/net/socket/ssl_server_socket_impl.cc
@@ -180,17 +180,17 @@
 
   // Used by Read function.
   scoped_refptr<IOBuffer> user_read_buf_;
-  int user_read_buf_len_;
+  int user_read_buf_len_ = 0;
 
   // Used by Write function.
   scoped_refptr<IOBuffer> user_write_buf_;
-  int user_write_buf_len_;
+  int user_write_buf_len_ = 0;
 
   // OpenSSL stuff
   bssl::UniquePtr<SSL> ssl_;
 
   // Whether we received any data in early data.
-  bool early_data_received_;
+  bool early_data_received_ = false;
 
   // StreamSocket for sending and receiving data.
   std::unique_ptr<StreamSocket> transport_socket_;
@@ -199,10 +199,10 @@
   // Certificate for the client.
   scoped_refptr<X509Certificate> client_cert_;
 
-  State next_handshake_state_;
-  bool completed_handshake_;
+  State next_handshake_state_ = STATE_NONE;
+  bool completed_handshake_ = false;
 
-  NextProto negotiated_protocol_;
+  NextProto negotiated_protocol_ = kProtoUnknown;
 
   base::WeakPtrFactory<SocketImpl> weak_factory_{this};
 };
@@ -212,13 +212,7 @@
     std::unique_ptr<StreamSocket> transport_socket)
     : context_(context),
       signature_result_(kSSLServerSocketNoPendingResult),
-      user_read_buf_len_(0),
-      user_write_buf_len_(0),
-      early_data_received_(false),
-      transport_socket_(std::move(transport_socket)),
-      next_handshake_state_(STATE_NONE),
-      completed_handshake_(false),
-      negotiated_protocol_(kProtoUnknown) {}
+      transport_socket_(std::move(transport_socket)) {}
 
 SSLServerContextImpl::SocketImpl::~SocketImpl() {
   if (ssl_) {
diff --git a/net/socket/ssl_server_socket_unittest.cc b/net/socket/ssl_server_socket_unittest.cc
index e59ce1da..1225c7aa 100644
--- a/net/socket/ssl_server_socket_unittest.cc
+++ b/net/socket/ssl_server_socket_unittest.cc
@@ -106,8 +106,7 @@
 
 class FakeDataChannel {
  public:
-  FakeDataChannel()
-      : read_buf_len_(0), closed_(false), write_called_after_close_(false) {}
+  FakeDataChannel() = default;
 
   FakeDataChannel(const FakeDataChannel&) = delete;
   FakeDataChannel& operator=(const FakeDataChannel&) = delete;
@@ -203,19 +202,19 @@
 
   CompletionOnceCallback read_callback_;
   scoped_refptr<IOBuffer> read_buf_;
-  int read_buf_len_;
+  int read_buf_len_ = 0;
 
   CompletionOnceCallback write_callback_;
 
   base::queue<scoped_refptr<DrainableIOBuffer>> data_;
 
   // True if Close() has been called.
-  bool closed_;
+  bool closed_ = false;
 
   // Controls the completion of Write() after the FakeDataChannel is closed.
   // After the FakeDataChannel is closed, the first Write() call completes
   // asynchronously.
-  bool write_called_after_close_;
+  bool write_called_after_close_ = false;
 
   base::WeakPtrFactory<FakeDataChannel> weak_factory_{this};
 };
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index 879ae08a..4d5d3f1b 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -295,7 +295,7 @@
 
 class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
  public:
-  TestSocketPerformanceWatcher() : connection_changed_count_(0u) {}
+  TestSocketPerformanceWatcher() = default;
 
   TestSocketPerformanceWatcher(const TestSocketPerformanceWatcher&) = delete;
   TestSocketPerformanceWatcher& operator=(const TestSocketPerformanceWatcher&) =
@@ -312,7 +312,7 @@
   size_t connection_changed_count() const { return connection_changed_count_; }
 
  private:
-  size_t connection_changed_count_;
+  size_t connection_changed_count_ = 0u;
 };
 
 // TestSocketPerformanceWatcher requires kernel support for tcp_info struct, and
diff --git a/net/socket/tcp_socket_posix.cc b/net/socket/tcp_socket_posix.cc
index 850ad7e..8d9f5bc 100644
--- a/net/socket/tcp_socket_posix.cc
+++ b/net/socket/tcp_socket_posix.cc
@@ -162,7 +162,6 @@
     NetLog* net_log,
     const NetLogSource& source)
     : socket_performance_watcher_(std::move(socket_performance_watcher)),
-      logging_multiple_connect_attempts_(false),
       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {
   net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
 }
diff --git a/net/socket/tcp_socket_posix.h b/net/socket/tcp_socket_posix.h
index c77ea723..7d5feff 100644
--- a/net/socket/tcp_socket_posix.h
+++ b/net/socket/tcp_socket_posix.h
@@ -218,7 +218,7 @@
   // |socket_performance_watcher_|. May be nullptr.
   std::unique_ptr<SocketPerformanceWatcher> socket_performance_watcher_;
 
-  bool logging_multiple_connect_attempts_;
+  bool logging_multiple_connect_attempts_ = false;
 
   NetLogWithSource net_log_;
 
diff --git a/net/socket/tcp_socket_unittest.cc b/net/socket/tcp_socket_unittest.cc
index 51f20a1..28264b4 100644
--- a/net/socket/tcp_socket_unittest.cc
+++ b/net/socket/tcp_socket_unittest.cc
@@ -82,9 +82,7 @@
 class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
  public:
   explicit TestSocketPerformanceWatcher(bool should_notify_updated_rtt)
-      : should_notify_updated_rtt_(should_notify_updated_rtt),
-        connection_changed_count_(0u),
-        rtt_notification_count_(0u) {}
+      : should_notify_updated_rtt_(should_notify_updated_rtt) {}
 
   TestSocketPerformanceWatcher(const TestSocketPerformanceWatcher&) = delete;
   TestSocketPerformanceWatcher& operator=(const TestSocketPerformanceWatcher&) =
@@ -108,8 +106,8 @@
 
  private:
   const bool should_notify_updated_rtt_;
-  size_t connection_changed_count_;
-  size_t rtt_notification_count_;
+  size_t connection_changed_count_ = 0u;
+  size_t rtt_notification_count_ = 0u;
 };
 
 const int kListenBacklog = 5;
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc
index 640f19d9..0d57f2cb 100644
--- a/net/socket/transport_client_socket_pool.cc
+++ b/net/socket/transport_client_socket_pool.cc
@@ -1440,10 +1440,7 @@
     TransportClientSocketPool* client_socket_pool)
     : group_id_(group_id),
       client_socket_pool_(client_socket_pool),
-      never_assigned_job_count_(0),
-      unbound_requests_(NUM_PRIORITIES),
-      active_socket_count_(0),
-      generation_(0) {}
+      unbound_requests_(NUM_PRIORITIES) {}
 
 TransportClientSocketPool::Group::~Group() {
   DCHECK_EQ(0u, never_assigned_job_count());
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h
index 92cec633..60de4755 100644
--- a/net/socket/transport_client_socket_pool.h
+++ b/net/socket/transport_client_socket_pool.h
@@ -529,7 +529,7 @@
     // preconnect and decremented when a preconnect is assigned, or when there
     // are fewer than |never_assigned_job_count_| ConnectJobs.  Not incremented
     // when a request is cancelled.
-    size_t never_assigned_job_count_;
+    size_t never_assigned_job_count_ = 0;
 
     std::list<IdleSocket> idle_sockets_;
     JobList jobs_;  // For bookkeeping purposes, there is a copy of the raw
@@ -538,7 +538,7 @@
                     // element of |unbound_requests_|.
     std::list<ConnectJob*> unassigned_jobs_;
     RequestQueue unbound_requests_;
-    int active_socket_count_;  // number of active sockets used by clients
+    int active_socket_count_ = 0;  // number of active sockets used by clients
     // A timer for when to start the backup job.
     base::OneShotTimer backup_job_timer_;
 
@@ -553,7 +553,7 @@
     // rather than reused. Destroying a group will reset the generation number,
     // but as that only happens once there are no outstanding sockets or
     // requests associated with the group, that's harmless.
-    int64_t generation_;
+    int64_t generation_ = 0;
   };
 
   using GroupMap = std::map<GroupId, Group*>;
diff --git a/net/socket/transport_client_socket_pool_test_util.cc b/net/socket/transport_client_socket_pool_test_util.cc
index ac4cc87..184f21a 100644
--- a/net/socket/transport_client_socket_pool_test_util.cc
+++ b/net/socket/transport_client_socket_pool_test_util.cc
@@ -44,8 +44,7 @@
 class MockConnectClientSocket : public TransportClientSocket {
  public:
   MockConnectClientSocket(const AddressList& addrlist, net::NetLog* net_log)
-      : connected_(false),
-        addrlist_(addrlist),
+      : addrlist_(addrlist),
         net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {}
 
   MockConnectClientSocket(const MockConnectClientSocket&) = delete;
@@ -106,7 +105,7 @@
   int SetSendBufferSize(int32_t size) override { return OK; }
 
  private:
-  bool connected_;
+  bool connected_ = false;
   const AddressList addrlist_;
   NetLogWithSource net_log_;
 };
@@ -186,7 +185,6 @@
                               Error connect_error,
                               net::NetLog* net_log)
       : connect_error_(connect_error),
-        is_connected_(false),
         addrlist_(addrlist),
         net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::SOCKET)) {}
 
@@ -299,7 +297,7 @@
   }
 
   Error connect_error_;
-  bool is_connected_;
+  bool is_connected_ = false;
   const AddressList addrlist_;
   NetLogWithSource net_log_;
   CompletionOnceCallback callback_;
@@ -364,8 +362,6 @@
 MockTransportClientSocketFactory::MockTransportClientSocketFactory(
     NetLog* net_log)
     : net_log_(net_log),
-      allocation_count_(0),
-      client_socket_type_(Type::kSynchronous),
       delay_(base::Milliseconds(ClientSocketPool::kMaxConnectRetryIntervalMs)) {
 }
 
diff --git a/net/socket/transport_client_socket_pool_test_util.h b/net/socket/transport_client_socket_pool_test_util.h
index b619bf2..01b73b7b 100644
--- a/net/socket/transport_client_socket_pool_test_util.h
+++ b/net/socket/transport_client_socket_pool_test_util.h
@@ -145,8 +145,8 @@
 
  private:
   raw_ptr<NetLog> net_log_;
-  int allocation_count_;
-  Type client_socket_type_;
+  int allocation_count_ = 0;
+  Type client_socket_type_ = Type::kSynchronous;
   base::span<const Rule> rules_;
   base::TimeDelta delay_;
   base::queue<base::OnceClosure> triggerable_sockets_;
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc
index 9d6af2d..3a6e3e1 100644
--- a/net/socket/transport_client_socket_pool_unittest.cc
+++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -862,8 +862,7 @@
       : group_id_(group_id),
         socket_params_(socket_params),
         handle_(handle),
-        pool_(pool),
-        within_callback_(false) {}
+        pool_(pool) {}
 
   RequestSocketCallback(const RequestSocketCallback&) = delete;
   RequestSocketCallback& operator=(const RequestSocketCallback&) = delete;
@@ -900,7 +899,7 @@
   scoped_refptr<ClientSocketPool::SocketParams> socket_params_;
   const raw_ptr<ClientSocketHandle> handle_;
   const raw_ptr<TransportClientSocketPool> pool_;
-  bool within_callback_;
+  bool within_callback_ = false;
 };
 
 TEST_F(TransportClientSocketPoolTest, RequestTwice) {
diff --git a/net/socket/transport_client_socket_unittest.cc b/net/socket/transport_client_socket_unittest.cc
index cd21ee5401..10ee954 100644
--- a/net/socket/transport_client_socket_unittest.cc
+++ b/net/socket/transport_client_socket_unittest.cc
@@ -45,8 +45,7 @@
                                   public WithTaskEnvironment {
  public:
   TransportClientSocketTest()
-      : listen_port_(0),
-        socket_factory_(ClientSocketFactory::GetDefaultFactory()) {}
+      : socket_factory_(ClientSocketFactory::GetDefaultFactory()) {}
 
   ~TransportClientSocketTest() override = default;
 
@@ -68,7 +67,7 @@
 
  protected:
   base::RunLoop connect_loop_;
-  uint16_t listen_port_;
+  uint16_t listen_port_ = 0;
   RecordingNetLogObserver net_log_observer_;
   const raw_ptr<ClientSocketFactory> socket_factory_;
   std::unique_ptr<StreamSocket> sock_;
diff --git a/net/socket/transport_connect_job.cc b/net/socket/transport_connect_job.cc
index 8024299..8361b39 100644
--- a/net/socket/transport_connect_job.cc
+++ b/net/socket/transport_connect_job.cc
@@ -132,8 +132,7 @@
                  net_log,
                  NetLogSourceType::TRANSPORT_CONNECT_JOB,
                  NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
-      params_(params),
-      next_state_(STATE_NONE) {
+      params_(params) {
   if (endpoint_result_override) {
     has_dns_override_ = true;
     endpoint_results_ = {std::move(endpoint_result_override->result)};
diff --git a/net/socket/transport_connect_job.h b/net/socket/transport_connect_job.h
index cb97bcb..029320656 100644
--- a/net/socket/transport_connect_job.h
+++ b/net/socket/transport_connect_job.h
@@ -217,7 +217,7 @@
   std::set<std::string> dns_aliases_;
   bool has_dns_override_ = false;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
 
   // The addresses are divided into IPv4 and IPv6, which are performed partially
   // in parallel. If the list of IPv6 addresses is non-empty, then the IPv6 jobs
diff --git a/net/socket/transport_connect_sub_job.cc b/net/socket/transport_connect_sub_job.cc
index 28c9834d..0de0bba 100644
--- a/net/socket/transport_connect_sub_job.cc
+++ b/net/socket/transport_connect_sub_job.cc
@@ -120,11 +120,7 @@
     std::vector<IPEndPoint> addresses,
     TransportConnectJob* parent_job,
     SubJobType type)
-    : parent_job_(parent_job),
-      addresses_(std::move(addresses)),
-      current_address_index_(0),
-      next_state_(STATE_NONE),
-      type_(type) {}
+    : parent_job_(parent_job), addresses_(std::move(addresses)), type_(type) {}
 
 TransportConnectSubJob::~TransportConnectSubJob() = default;
 
diff --git a/net/socket/transport_connect_sub_job.h b/net/socket/transport_connect_sub_job.h
index 09682264..807635a 100644
--- a/net/socket/transport_connect_sub_job.h
+++ b/net/socket/transport_connect_sub_job.h
@@ -75,9 +75,9 @@
   const raw_ptr<TransportConnectJob> parent_job_;
 
   std::vector<IPEndPoint> addresses_;
-  size_t current_address_index_;
+  size_t current_address_index_ = 0;
 
-  State next_state_;
+  State next_state_ = STATE_NONE;
   const SubJobType type_;
 
   std::unique_ptr<StreamSocket> transport_socket_;
diff --git a/net/socket/udp_server_socket.cc b/net/socket/udp_server_socket.cc
index 58129d58..e16084b6 100644
--- a/net/socket/udp_server_socket.cc
+++ b/net/socket/udp_server_socket.cc
@@ -13,10 +13,7 @@
 
 UDPServerSocket::UDPServerSocket(net::NetLog* net_log,
                                  const net::NetLogSource& source)
-    : socket_(DatagramSocket::DEFAULT_BIND, net_log, source),
-      allow_address_reuse_(false),
-      allow_broadcast_(false),
-      allow_address_sharing_for_multicast_(false) {}
+    : socket_(DatagramSocket::DEFAULT_BIND, net_log, source) {}
 
 UDPServerSocket::~UDPServerSocket() = default;
 
diff --git a/net/socket/udp_server_socket.h b/net/socket/udp_server_socket.h
index 9006f4e..1e51ccdd 100644
--- a/net/socket/udp_server_socket.h
+++ b/net/socket/udp_server_socket.h
@@ -61,9 +61,9 @@
 
  private:
   UDPSocket socket_;
-  bool allow_address_reuse_;
-  bool allow_broadcast_;
-  bool allow_address_sharing_for_multicast_;
+  bool allow_address_reuse_ = false;
+  bool allow_broadcast_ = false;
+  bool allow_address_sharing_for_multicast_ = false;
 };
 
 }  // namespace net
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
index c4b33de..8dfabde 100644
--- a/net/socket/udp_socket_posix.cc
+++ b/net/socket/udp_socket_posix.cc
@@ -133,29 +133,16 @@
     : write_async_watcher_(std::make_unique<WriteAsyncWatcher>(this)),
       sender_(new UDPSocketPosixSender()),
       socket_(kInvalidSocket),
-      socket_hash_(0),
-      addr_family_(0),
-      is_connected_(false),
-      socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
-      sendto_flags_(0),
-      multicast_interface_(0),
-      multicast_time_to_live_(1),
       bind_type_(bind_type),
       read_socket_watcher_(FROM_HERE),
       write_socket_watcher_(FROM_HERE),
       read_watcher_(this),
       write_watcher_(this),
-      last_async_result_(0),
-      write_async_timer_running_(false),
-      write_async_outstanding_(0),
-      read_buf_len_(0),
       recv_from_address_(nullptr),
-      write_buf_len_(0),
       net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)),
       bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle),
       always_update_bytes_received_(base::FeatureList::IsEnabled(
-          features::kUdpSocketPosixAlwaysUpdateBytesReceived)),
-      experimental_recv_optimization_enabled_(false) {
+          features::kUdpSocketPosixAlwaysUpdateBytesReceived)) {
   net_log_.BeginEventReferencingSource(NetLogEventType::SOCKET_ALIVE, source);
 }
 
@@ -1077,11 +1064,11 @@
   tag_ = tag;
 }
 
-UDPSocketPosixSender::UDPSocketPosixSender() : sendmmsg_enabled_(false) {}
-UDPSocketPosixSender::~UDPSocketPosixSender() {}
+UDPSocketPosixSender::UDPSocketPosixSender() = default;
+UDPSocketPosixSender::~UDPSocketPosixSender() = default;
 
 SendResult::SendResult() : rv(0), write_count(0) {}
-SendResult::~SendResult() {}
+SendResult::~SendResult() = default;
 SendResult::SendResult(int _rv, int _write_count, DatagramBuffers _buffers)
     : rv(_rv), write_count(_write_count), buffers(std::move(_buffers)) {}
 SendResult::SendResult(SendResult&& other) = default;
diff --git a/net/socket/udp_socket_posix.h b/net/socket/udp_socket_posix.h
index 9bd2e6d0..351c305 100644
--- a/net/socket/udp_socket_posix.h
+++ b/net/socket/udp_socket_posix.h
@@ -84,6 +84,9 @@
  public:
   UDPSocketPosixSender();
 
+  UDPSocketPosixSender(const UDPSocketPosixSender&) = delete;
+  UDPSocketPosixSender& operator=(const UDPSocketPosixSender&) = delete;
+
   SendResult SendBuffers(int fd, DatagramBuffers buffers);
 
   void SetSendmmsgEnabled(bool enabled) {
@@ -113,9 +116,7 @@
 #endif
 
  private:
-  UDPSocketPosixSender(const UDPSocketPosixSender&) = delete;
-  UDPSocketPosixSender& operator=(const UDPSocketPosixSender&) = delete;
-  bool sendmmsg_enabled_;
+  bool sendmmsg_enabled_ = false;
 };
 
 class NET_EXPORT UDPSocketPosix {
@@ -127,7 +128,7 @@
   // throughput estimate.
   class ReceivedActivityMonitor {
    public:
-    ReceivedActivityMonitor() : bytes_(0), increments_(0) {}
+    ReceivedActivityMonitor() = default;
 
     ReceivedActivityMonitor(const ReceivedActivityMonitor&) = delete;
     ReceivedActivityMonitor& operator=(const ReceivedActivityMonitor&) = delete;
@@ -143,8 +144,8 @@
     void Update();
     void OnTimerFired();
 
-    uint32_t bytes_;
-    uint32_t increments_;
+    uint32_t bytes_ = 0;
+    uint32_t increments_ = 0;
     base::RepeatingTimer timer_;
   };
 
@@ -391,8 +392,7 @@
   // Watcher for WriteAsync paths.
   class WriteAsyncWatcher : public base::MessagePumpForIO::FdWatcher {
    public:
-    explicit WriteAsyncWatcher(UDPSocketPosix* socket)
-        : socket_(socket), watching_(false) {}
+    explicit WriteAsyncWatcher(UDPSocketPosix* socket) : socket_(socket) {}
 
     WriteAsyncWatcher(const WriteAsyncWatcher&) = delete;
     WriteAsyncWatcher& operator=(const WriteAsyncWatcher&) = delete;
@@ -409,7 +409,7 @@
 
    private:
     const raw_ptr<UDPSocketPosix> socket_;
-    bool watching_;
+    bool watching_ = false;
   };
 
   void IncreaseWriteAsyncOutstanding(int increment) {
@@ -544,24 +544,24 @@
   // Hash of |socket_| to verify that it is not corrupted when calling close().
   // Used to debug https://crbug.com/906005.
   // TODO(crbug.com/906005): Remove this once the bug is fixed.
-  int socket_hash_;
+  int socket_hash_ = 0;
 
-  int addr_family_;
-  bool is_connected_;
+  int addr_family_ = 0;
+  bool is_connected_ = false;
 
   // Bitwise-or'd combination of SocketOptions. Specifies the set of
   // options that should be applied to |socket_| before Bind().
-  int socket_options_;
+  int socket_options_ = SOCKET_OPTION_MULTICAST_LOOP;
 
   // Flags passed to sendto().
-  int sendto_flags_;
+  int sendto_flags_ = 0;
 
   // Multicast interface.
-  uint32_t multicast_interface_;
+  uint32_t multicast_interface_ = 0;
 
   // Multicast socket options cached for SetMulticastOption.
   // Cannot be used after Bind().
-  int multicast_time_to_live_;
+  int multicast_time_to_live_ = 1;
 
   // How to do source port binding, used only when UDPSocket is part of
   // UDPClientSocket, since UDPServerSocket provides Bind.
@@ -587,22 +587,22 @@
   int write_async_max_buffers_ = 16;
   int written_bytes_ = 0;
 
-  int last_async_result_;
+  int last_async_result_ = 0;
   base::RepeatingTimer write_async_timer_;
-  bool write_async_timer_running_;
+  bool write_async_timer_running_ = false;
   // Total writes in flight, including those |PostTask*|'d.
-  int write_async_outstanding_;
+  int write_async_outstanding_ = 0;
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   // The buffer used by InternalRead() to retry Read requests
   scoped_refptr<IOBuffer> read_buf_;
-  int read_buf_len_;
+  int read_buf_len_ = 0;
   raw_ptr<IPEndPoint> recv_from_address_;
 
   // The buffer used by InternalWrite() to retry Write requests
   scoped_refptr<IOBuffer> write_buf_;
-  int write_buf_len_;
+  int write_buf_len_ = 0;
   std::unique_ptr<IPEndPoint> send_to_address_;
 
   // External callback; called when read is complete.
@@ -634,7 +634,7 @@
   // By default, the value is set to false. To use the optimization, the
   // client of the socket has to opt-in by calling the
   // enable_experimental_recv_optimization() method.
-  bool experimental_recv_optimization_enabled_;
+  bool experimental_recv_optimization_enabled_ = false;
 
   // Manages decrementing the global open UDP socket counter when this
   // UDPSocket is destroyed.
diff --git a/net/socket/udp_socket_posix_unittest.cc b/net/socket/udp_socket_posix_unittest.cc
index 3fa290a..fc30635 100644
--- a/net/socket/udp_socket_posix_unittest.cc
+++ b/net/socket/udp_socket_posix_unittest.cc
@@ -133,8 +133,7 @@
   UDPSocketPosixTest()
       : TestWithTaskEnvironment(
             base::test::TaskEnvironment::TimeSource::MOCK_TIME),
-        socket_(DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource()),
-        callback_fired_(false) {
+        socket_(DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource()) {
     write_callback_ = base::BindRepeating(&UDPSocketPosixTest::OnWriteComplete,
                                           weak_factory_.GetWeakPtr());
   }
@@ -223,7 +222,7 @@
   RecordingNetLogObserver net_log_observer_;
   MockUDPSocketPosix socket_;
   DatagramBuffers buffers_;
-  bool callback_fired_;
+  bool callback_fired_ = false;
   int rv_;
   std::string msgs_[kNumMsgs] = {kHelloMsg, kSecondMsg, kThirdMsg};
   int lengths_[kNumMsgs] = {static_cast<int>(kHelloMsg.length()),
diff --git a/net/socket/websocket_endpoint_lock_manager.cc b/net/socket/websocket_endpoint_lock_manager.cc
index 16573d6..172bf9e 100644
--- a/net/socket/websocket_endpoint_lock_manager.cc
+++ b/net/socket/websocket_endpoint_lock_manager.cc
@@ -47,8 +47,7 @@
 }
 
 WebSocketEndpointLockManager::WebSocketEndpointLockManager()
-    : unlock_delay_(base::Milliseconds(kUnlockDelayInMs)),
-      pending_unlock_count_(0) {}
+    : unlock_delay_(base::Milliseconds(kUnlockDelayInMs)) {}
 
 WebSocketEndpointLockManager::~WebSocketEndpointLockManager() {
   DCHECK_EQ(lock_info_map_.size(), pending_unlock_count_);
diff --git a/net/socket/websocket_endpoint_lock_manager.h b/net/socket/websocket_endpoint_lock_manager.h
index b8fcc83..1d9719ba 100644
--- a/net/socket/websocket_endpoint_lock_manager.h
+++ b/net/socket/websocket_endpoint_lock_manager.h
@@ -134,7 +134,7 @@
   base::TimeDelta unlock_delay_;
 
   // Number of sockets currently pending unlock.
-  size_t pending_unlock_count_;
+  size_t pending_unlock_count_ = 0;
 
   base::WeakPtrFactory<WebSocketEndpointLockManager> weak_factory_{this};
 };
diff --git a/net/socket/websocket_endpoint_lock_manager_unittest.cc b/net/socket/websocket_endpoint_lock_manager_unittest.cc
index c6ca3bd..ccfe1a09 100644
--- a/net/socket/websocket_endpoint_lock_manager_unittest.cc
+++ b/net/socket/websocket_endpoint_lock_manager_unittest.cc
@@ -26,7 +26,7 @@
 
 class FakeWaiter : public WebSocketEndpointLockManager::Waiter {
  public:
-  FakeWaiter() : called_(false) {}
+  FakeWaiter() = default;
 
   void GotEndpointLock() override {
     CHECK(!called_);
@@ -36,7 +36,7 @@
   bool called() const { return called_; }
 
  private:
-  bool called_;
+  bool called_ = false;
 };
 
 class BlockingWaiter : public FakeWaiter {
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc
index e0be94d..b1f7cd2 100644
--- a/net/socket/websocket_transport_client_socket_pool.cc
+++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -37,9 +37,7 @@
                        common_connect_job_params,
                        std::make_unique<ConnectJobFactory>()),
       proxy_server_(proxy_server),
-      max_sockets_(max_sockets),
-      handed_out_socket_count_(0),
-      flushing_(false) {
+      max_sockets_(max_sockets) {
   DCHECK(common_connect_job_params->websocket_endpoint_lock_manager);
 }
 
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h
index 97a1716..2f88e43f 100644
--- a/net/socket/websocket_transport_client_socket_pool.h
+++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -203,8 +203,8 @@
   StalledRequestQueue stalled_request_queue_;
   StalledRequestMap stalled_request_map_;
   const int max_sockets_;
-  int handed_out_socket_count_;
-  bool flushing_;
+  int handed_out_socket_count_ = 0;
+  bool flushing_ = false;
 
   base::WeakPtrFactory<WebSocketTransportClientSocketPool> weak_factory_{this};
 };
diff --git a/net/spdy/bidirectional_stream_spdy_impl.cc b/net/spdy/bidirectional_stream_spdy_impl.cc
index 7f05167..4b443a4b 100644
--- a/net/spdy/bidirectional_stream_spdy_impl.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl.cc
@@ -35,17 +35,7 @@
     : spdy_session_(spdy_session),
       request_info_(nullptr),
       delegate_(nullptr),
-      source_dependency_(source_dependency),
-      negotiated_protocol_(kProtoUnknown),
-      more_read_data_pending_(false),
-      read_buffer_len_(0),
-      written_end_of_stream_(false),
-      write_pending_(false),
-      stream_closed_(false),
-      closed_stream_status_(ERR_FAILED),
-      closed_stream_received_bytes_(0),
-      closed_stream_sent_bytes_(0),
-      closed_has_load_timing_info_(false) {}
+      source_dependency_(source_dependency) {}
 
 BidirectionalStreamSpdyImpl::~BidirectionalStreamSpdyImpl() {
   // Sends a RST to the remote if the stream is destroyed before it completes.
diff --git a/net/spdy/bidirectional_stream_spdy_impl.h b/net/spdy/bidirectional_stream_spdy_impl.h
index 4f434eb..41ef997 100644
--- a/net/spdy/bidirectional_stream_spdy_impl.h
+++ b/net/spdy/bidirectional_stream_spdy_impl.h
@@ -98,34 +98,34 @@
   base::WeakPtr<SpdyStream> stream_;
   const NetLogSource source_dependency_;
 
-  NextProto negotiated_protocol_;
+  NextProto negotiated_protocol_ = kProtoUnknown;
 
   // Buffers the data as it arrives asynchronously from the stream.
   SpdyReadQueue read_data_queue_;
   // Whether received more data has arrived since started waiting.
-  bool more_read_data_pending_;
+  bool more_read_data_pending_ = false;
   // User provided read buffer for ReadData() response.
   scoped_refptr<IOBuffer> read_buffer_;
-  int read_buffer_len_;
+  int read_buffer_len_ = 0;
 
   // Whether client has written the end of stream flag in request headers or
   // in SendData()/SendvData().
-  bool written_end_of_stream_;
+  bool written_end_of_stream_ = false;
   // Whether a SendData() or SendvData() is pending.
-  bool write_pending_;
+  bool write_pending_ = false;
 
   // Whether OnClose has been invoked.
-  bool stream_closed_;
+  bool stream_closed_ = false;
   // Status reported in OnClose.
-  int closed_stream_status_;
+  int closed_stream_status_ = ERR_FAILED;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes received over the network for |stream_| while it was open.
-  int64_t closed_stream_received_bytes_;
+  int64_t closed_stream_received_bytes_ = 0;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes sent over the network for |stream_| while it was open.
-  int64_t closed_stream_sent_bytes_;
+  int64_t closed_stream_sent_bytes_ = 0;
   // True if |stream_| has LoadTimingInfo when it is closed.
-  bool closed_has_load_timing_info_;
+  bool closed_has_load_timing_info_ = false;
   // LoadTimingInfo populated when |stream_| is closed.
   LoadTimingInfo closed_load_timing_info_;
 
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
index 36bd3af..94d6338 100644
--- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -76,15 +76,7 @@
                                                               NetLogSource())),
         read_buf_(read_buf),
         read_buf_len_(read_buf_len),
-        loop_(nullptr),
-        error_(OK),
-        bytes_read_(0),
-        on_data_read_count_(0),
-        on_data_sent_count_(0),
-        do_not_start_read_(false),
-        run_until_completion_(false),
-        not_expect_callback_(false),
-        on_failed_called_(false) {}
+        loop_(nullptr) {}
 
   TestDelegateBase(const TestDelegateBase&) = delete;
   TestDelegateBase& operator=(const TestDelegateBase&) = delete;
@@ -228,14 +220,14 @@
   std::unique_ptr<base::RunLoop> loop_;
   spdy::Http2HeaderBlock response_headers_;
   spdy::Http2HeaderBlock trailers_;
-  int error_;
-  int bytes_read_;
-  int on_data_read_count_;
-  int on_data_sent_count_;
-  bool do_not_start_read_;
-  bool run_until_completion_;
-  bool not_expect_callback_;
-  bool on_failed_called_;
+  int error_ = OK;
+  int bytes_read_ = 0;
+  int on_data_read_count_ = 0;
+  int on_data_sent_count_ = 0;
+  bool do_not_start_read_ = false;
+  bool run_until_completion_ = false;
+  bool not_expect_callback_ = false;
+  bool on_failed_called_ = false;
 };
 
 }  // namespace
diff --git a/net/spdy/buffered_spdy_framer.cc b/net/spdy/buffered_spdy_framer.cc
index 93ffc6f6..913efea 100644
--- a/net/spdy/buffered_spdy_framer.cc
+++ b/net/spdy/buffered_spdy_framer.cc
@@ -26,7 +26,6 @@
                                        TimeFunc time_func)
     : spdy_framer_(spdy::SpdyFramer::ENABLE_COMPRESSION),
       visitor_(nullptr),
-      frames_received_(0),
       max_header_list_size_(max_header_list_size),
       net_log_(net_log),
       time_func_(time_func) {
diff --git a/net/spdy/buffered_spdy_framer_unittest.cc b/net/spdy/buffered_spdy_framer_unittest.cc
index 4f4efb8..1e0d4f6e 100644
--- a/net/spdy/buffered_spdy_framer_unittest.cc
+++ b/net/spdy/buffered_spdy_framer_unittest.cc
@@ -20,12 +20,6 @@
  public:
   TestBufferedSpdyVisitor()
       : buffered_spdy_framer_(kMaxHeaderListSizeForTest, NetLogWithSource()),
-        error_count_(0),
-        setting_count_(0),
-        headers_frame_count_(0),
-        push_promise_frame_count_(0),
-        goaway_count_(0),
-        altsvc_count_(0),
         header_stream_id_(static_cast<spdy::SpdyStreamId>(-1)),
         promised_stream_id_(static_cast<spdy::SpdyStreamId>(-1)) {}
 
@@ -157,12 +151,12 @@
   BufferedSpdyFramer buffered_spdy_framer_;
 
   // Counters from the visitor callbacks.
-  int error_count_;
-  int setting_count_;
-  int headers_frame_count_;
-  int push_promise_frame_count_;
-  int goaway_count_;
-  int altsvc_count_;
+  int error_count_ = 0;
+  int setting_count_ = 0;
+  int headers_frame_count_ = 0;
+  int push_promise_frame_count_ = 0;
+  int goaway_count_ = 0;
+  int altsvc_count_ = 0;
 
   // Header block streaming state:
   spdy::SpdyStreamId header_stream_id_;
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.cc b/net/spdy/fuzzing/hpack_fuzz_util.cc
index d0f1c61..b30544c 100644
--- a/net/spdy/fuzzing/hpack_fuzz_util.cc
+++ b/net/spdy/fuzzing/hpack_fuzz_util.cc
@@ -38,7 +38,7 @@
 HpackFuzzUtil::GeneratorContext::GeneratorContext() = default;
 HpackFuzzUtil::GeneratorContext::~GeneratorContext() = default;
 
-HpackFuzzUtil::Input::Input() : offset(0) {}
+HpackFuzzUtil::Input::Input() = default;
 HpackFuzzUtil::Input::~Input() = default;
 
 HpackFuzzUtil::FuzzerContext::FuzzerContext() = default;
diff --git a/net/spdy/fuzzing/hpack_fuzz_util.h b/net/spdy/fuzzing/hpack_fuzz_util.h
index e629f18..c23602c0 100644
--- a/net/spdy/fuzzing/hpack_fuzz_util.h
+++ b/net/spdy/fuzzing/hpack_fuzz_util.h
@@ -46,7 +46,7 @@
     const char* ptr() { return input.data() + offset; }
 
     std::string input;
-    size_t offset;
+    size_t offset = 0;
   };
 
   // Returns true if the next header block was set at |out|. Returns
diff --git a/net/spdy/http2_priority_dependencies_unittest.cc b/net/spdy/http2_priority_dependencies_unittest.cc
index eb8ee47..5f511a7f 100644
--- a/net/spdy/http2_priority_dependencies_unittest.cc
+++ b/net/spdy/http2_priority_dependencies_unittest.cc
@@ -31,7 +31,7 @@
 
 class HttpPriorityDependencyTest : public PlatformTest {
  public:
-  HttpPriorityDependencyTest() : next_id_(0u) {}
+  HttpPriorityDependencyTest() = default;
 
   // Fixed priority values to use for testing.
   enum {
@@ -92,7 +92,7 @@
   }
 
  private:
-  spdy::SpdyStreamId next_id_;
+  spdy::SpdyStreamId next_id_ = 0u;
   Http2PriorityDependencies dependency_state_;
 };
 
diff --git a/net/spdy/spdy_http_stream.cc b/net/spdy/spdy_http_stream.cc
index f4db5b6..dd9588c 100644
--- a/net/spdy/spdy_http_stream.cc
+++ b/net/spdy/spdy_http_stream.cc
@@ -110,19 +110,8 @@
       pushed_stream_id_(pushed_stream_id),
       is_reused_(spdy_session_->IsReused()),
       source_dependency_(source_dependency),
-      stream_(nullptr),
-      stream_closed_(false),
-      closed_stream_status_(ERR_FAILED),
-      closed_stream_id_(0),
-      closed_stream_received_bytes_(0),
-      closed_stream_sent_bytes_(0),
       request_info_(nullptr),
       response_info_(nullptr),
-      response_headers_complete_(false),
-      upload_stream_in_progress_(false),
-      user_buffer_len_(0),
-      request_body_buf_size_(0),
-      was_alpn_negotiated_(false),
       dns_aliases_(std::move(dns_aliases)) {
   DCHECK(spdy_session_.get());
 }
diff --git a/net/spdy/spdy_http_stream.h b/net/spdy/spdy_http_stream.h
index 7dfc6e8..513b3d6 100644
--- a/net/spdy/spdy_http_stream.h
+++ b/net/spdy/spdy_http_stream.h
@@ -167,22 +167,22 @@
   // After InitializeStream() is called but before OnClose() is called,
   //   |*stream_| is guaranteed to be valid.
   // After OnClose() is called, stream_ == nullptr.
-  SpdyStream* stream_;
+  SpdyStream* stream_ = nullptr;
 
   // False before OnClose() is called, true after.
-  bool stream_closed_;
+  bool stream_closed_ = false;
 
   // Set only when |stream_closed_| is true.
-  int closed_stream_status_;
-  spdy::SpdyStreamId closed_stream_id_;
+  int closed_stream_status_ = ERR_FAILED;
+  spdy::SpdyStreamId closed_stream_id_ = 0;
   bool closed_stream_has_load_timing_info_;
   LoadTimingInfo closed_stream_load_timing_info_;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes received over the network for |stream_| while it was open.
-  int64_t closed_stream_received_bytes_;
+  int64_t closed_stream_received_bytes_ = 0;
   // After |stream_| has been closed, this keeps track of the total number of
   // bytes sent over the network for |stream_| while it was open.
-  int64_t closed_stream_sent_bytes_;
+  int64_t closed_stream_sent_bytes_ = 0;
 
   // The request to send.
   // Set to null before response body is starting to be read. This is to allow
@@ -198,9 +198,9 @@
 
   std::unique_ptr<HttpResponseInfo> push_response_info_;
 
-  bool response_headers_complete_;
+  bool response_headers_complete_ = false;
 
-  bool upload_stream_in_progress_;
+  bool upload_stream_in_progress_ = false;
 
   // We buffer the response body as it arrives asynchronously from the stream.
   SpdyReadQueue response_body_queue_;
@@ -210,16 +210,16 @@
 
   // User provided buffer for the ReadResponseBody() response.
   scoped_refptr<IOBuffer> user_buffer_;
-  int user_buffer_len_;
+  int user_buffer_len_ = 0;
 
   // Temporary buffer used to read the request body from UploadDataStream.
   scoped_refptr<IOBufferWithSize> request_body_buf_;
-  int request_body_buf_size_;
+  int request_body_buf_size_ = 0;
 
   // Timer to execute DoBufferedReadCallback() with a delay.
   base::OneShotTimer buffered_read_timer_;
 
-  bool was_alpn_negotiated_;
+  bool was_alpn_negotiated_ = false;
 
   // Stores any DNS aliases for the remote endpoint. Includes all known aliases,
   // e.g. from A, AAAA, or HTTPS, not just from the address used for the
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
index 693b1b1..273b456 100644
--- a/net/spdy/spdy_proxy_client_socket.cc
+++ b/net/spdy/spdy_proxy_client_socket.cc
@@ -46,9 +46,6 @@
       proxy_server_(proxy_server),
       proxy_delegate_(proxy_delegate),
       user_agent_(user_agent),
-      user_buffer_len_(0),
-      write_buffer_len_(0),
-      was_ever_used_(false),
       net_log_(NetLogWithSource::Make(spdy_stream->net_log().net_log(),
                                       NetLogSourceType::PROXY_CLIENT_SOCKET)),
       source_dependency_(source_net_log.source()) {
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
index c0aef4d8..b2a2e4a 100644
--- a/net/spdy/spdy_proxy_client_socket.h
+++ b/net/spdy/spdy_proxy_client_socket.h
@@ -173,13 +173,13 @@
 
   // User provided buffer for the Read() response.
   scoped_refptr<IOBuffer> user_buffer_;
-  size_t user_buffer_len_;
+  size_t user_buffer_len_ = 0;
 
   // User specified number of bytes to be written.
-  int write_buffer_len_;
+  int write_buffer_len_ = 0;
 
   // True if the transport socket has ever sent data.
-  bool was_ever_used_;
+  bool was_ever_used_ = false;
 
   const NetLogWithSource net_log_;
   const NetLogSource source_dependency_;
diff --git a/net/spdy/spdy_read_queue.cc b/net/spdy/spdy_read_queue.cc
index 48ace9b..81d93ba 100644
--- a/net/spdy/spdy_read_queue.cc
+++ b/net/spdy/spdy_read_queue.cc
@@ -12,7 +12,7 @@
 
 namespace net {
 
-SpdyReadQueue::SpdyReadQueue() : total_size_(0) {}
+SpdyReadQueue::SpdyReadQueue() = default;
 
 SpdyReadQueue::~SpdyReadQueue() {
   Clear();
diff --git a/net/spdy/spdy_read_queue.h b/net/spdy/spdy_read_queue.h
index 205e85c..41d73fc 100644
--- a/net/spdy/spdy_read_queue.h
+++ b/net/spdy/spdy_read_queue.h
@@ -46,7 +46,7 @@
   // Class invariant:
   // |total_size_| is the sum of GetRemainingSize() of |queue_|'s elements.
   base::circular_deque<std::unique_ptr<SpdyBuffer>> queue_;
-  size_t total_size_;
+  size_t total_size_ = 0;
 };
 
 }  // namespace net
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 148ac4f..fe41ff9 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -935,53 +935,25 @@
     ServerPushDelegate* push_delegate,
     NetworkQualityEstimator* network_quality_estimator,
     NetLog* net_log)
-    : in_io_loop_(false),
-      spdy_session_key_(spdy_session_key),
+    : spdy_session_key_(spdy_session_key),
       pool_(nullptr),
       http_server_properties_(http_server_properties),
       transport_security_state_(transport_security_state),
       ssl_config_service_(ssl_config_service),
       socket_(nullptr),
       stream_hi_water_mark_(kFirstStreamId),
-      last_accepted_push_stream_id_(0),
       push_delegate_(push_delegate),
-      num_pushed_streams_(0u),
-      num_active_pushed_streams_(0u),
-      bytes_pushed_count_(0u),
-      bytes_pushed_and_unclaimed_count_(0u),
-      in_flight_write_frame_type_(spdy::SpdyFrameType::DATA),
-      in_flight_write_frame_size_(0),
-      availability_state_(STATE_AVAILABLE),
-      read_state_(READ_STATE_DO_READ),
-      write_state_(WRITE_STATE_IDLE),
-      error_on_close_(OK),
       initial_settings_(initial_settings),
       enable_http2_settings_grease_(enable_http2_settings_grease),
       greased_http2_frame_(greased_http2_frame),
       http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame),
       enable_priority_update_(enable_priority_update),
-      deprecate_http2_priorities_(false),
-      settings_frame_received_(false),
-      in_confirm_handshake_(false),
       max_concurrent_streams_(kInitialMaxConcurrentStreams),
       max_concurrent_pushed_streams_(
           initial_settings.at(spdy::SETTINGS_MAX_CONCURRENT_STREAMS)),
-      streams_initiated_count_(0),
-      streams_pushed_count_(0),
-      streams_pushed_and_claimed_count_(0),
-      streams_abandoned_count_(0),
-      ping_in_flight_(false),
-      check_connection_on_radio_wakeup_(false),
-      next_ping_id_(1),
       last_read_time_(time_func()),
-      last_compressed_frame_len_(0),
-      check_ping_status_pending_(false),
-      session_send_window_size_(0),
       session_max_recv_window_size_(session_max_recv_window_size),
       session_max_queued_capped_frames_(session_max_queued_capped_frames),
-      broken_connection_detection_requests_(0),
-      session_recv_window_size_(0),
-      session_unacked_recv_window_bytes_(0),
       last_recv_window_update_(base::TimeTicks::Now()),
       time_to_buffer_small_window_updates_(
           kDefaultTimeToBufferSmallWindowUpdates),
@@ -999,7 +971,6 @@
       is_http2_enabled_(is_http2_enabled),
       is_quic_enabled_(is_quic_enabled),
       enable_push_(IsPushEnabled(initial_settings)),
-      support_websocket_(false),
       connection_at_risk_of_loss_time_(
           base::Seconds(kDefaultConnectionAtRiskOfLossSeconds)),
       hung_interval_(base::Seconds(kHungIntervalSeconds)),
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 4566fbe..e3437454 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -1076,7 +1076,7 @@
 
   // Whether Do{Read,Write}Loop() is in the call stack. Useful for
   // making sure we don't destroy ourselves prematurely in that case.
-  bool in_io_loop_;
+  bool in_io_loop_ = false;
 
   // The key used to identify this session.
   SpdySessionKey spdy_session_key_;
@@ -1112,7 +1112,7 @@
   spdy::SpdyStreamId stream_hi_water_mark_;  // The next stream id to use.
 
   // Used to ensure the server increments push stream ids correctly.
-  spdy::SpdyStreamId last_accepted_push_stream_id_;
+  spdy::SpdyStreamId last_accepted_push_stream_id_ = 0;
 
   // Queue, for each priority, of pending stream requests that have
   // not yet been satisfied.
@@ -1143,18 +1143,18 @@
   // Number of pushed streams. All active streams are stored in
   // |active_streams_|, but it's better to know the number of push streams
   // without traversing the whole collection.
-  size_t num_pushed_streams_;
+  size_t num_pushed_streams_ = 0u;
 
   // Number of active pushed streams in |active_streams_|, i.e. not in reserved
   // remote state. Streams in reserved state are not counted towards any
   // concurrency limits.
-  size_t num_active_pushed_streams_;
+  size_t num_active_pushed_streams_ = 0u;
 
   // Number of bytes that has been pushed by the server.
-  uint64_t bytes_pushed_count_;
+  uint64_t bytes_pushed_count_ = 0u;
 
   // Number of bytes that has been pushed by the server but never claimed.
-  uint64_t bytes_pushed_and_unclaimed_count_;
+  uint64_t bytes_pushed_and_unclaimed_count_ = 0u;
 
   // The write queue.
   SpdyWriteQueue write_queue_;
@@ -1164,9 +1164,9 @@
   // The buffer we're currently writing.
   std::unique_ptr<SpdyBuffer> in_flight_write_;
   // The type of the frame in |in_flight_write_|.
-  spdy::SpdyFrameType in_flight_write_frame_type_;
+  spdy::SpdyFrameType in_flight_write_frame_type_ = spdy::SpdyFrameType::DATA;
   // The size of the frame in |in_flight_write_|.
-  size_t in_flight_write_frame_size_;
+  size_t in_flight_write_frame_size_ = 0;
   // The stream to notify when |in_flight_write_| has been written to
   // the socket completely.
   base::WeakPtr<SpdyStream> in_flight_write_stream_;
@@ -1178,15 +1178,15 @@
   std::unique_ptr<BufferedSpdyFramer> buffered_spdy_framer_;
 
   // The state variables.
-  AvailabilityState availability_state_;
-  ReadState read_state_;
-  WriteState write_state_;
+  AvailabilityState availability_state_ = STATE_AVAILABLE;
+  ReadState read_state_ = READ_STATE_DO_READ;
+  WriteState write_state_ = WRITE_STATE_IDLE;
 
   // If the session is closing (i.e., |availability_state_| is STATE_DRAINING),
   // then |error_on_close_| holds the error with which it was closed, which
   // may be OK (upon a polite GOAWAY) or an error < ERR_IO_PENDING otherwise.
   // Initialized to OK.
-  Error error_on_close_;
+  Error error_on_close_ = OK;
 
   // Settings that are sent in the initial SETTINGS frame
   // (if |enable_sending_initial_data_| is true),
@@ -1223,31 +1223,31 @@
 
   // The value of the last received SETTINGS_DEPRECATE_HTTP2_PRIORITIES, with 0
   // mapping to false and 1 to true.  Initial value is false.
-  bool deprecate_http2_priorities_;
+  bool deprecate_http2_priorities_ = false;
 
   // True if at least one SETTINGS frame has been received.
-  bool settings_frame_received_;
+  bool settings_frame_received_ = false;
 
   // The callbacks to notify a request that the handshake has been confirmed.
   std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_;
 
   // True if there is an ongoing handshake confirmation with outstanding
   // requests.
-  bool in_confirm_handshake_;
+  bool in_confirm_handshake_ = false;
 
   // Limits
   size_t max_concurrent_streams_;
   size_t max_concurrent_pushed_streams_;
 
   // Some statistics counters for the session.
-  int streams_initiated_count_;
-  int streams_pushed_count_;
-  int streams_pushed_and_claimed_count_;
-  int streams_abandoned_count_;
+  int streams_initiated_count_ = 0;
+  int streams_pushed_count_ = 0;
+  int streams_pushed_and_claimed_count_ = 0;
+  int streams_abandoned_count_ = 0;
 
   // True if there has been a ping sent for which we have not received a
   // response yet.  There is always at most one ping in flight.
-  bool ping_in_flight_;
+  bool ping_in_flight_ = false;
 
   // Triggers periodic connection status checks.
   base::OneShotTimer heartbeat_timer_;
@@ -1256,10 +1256,10 @@
   base::TimeDelta heartbeat_interval_;
 
   // True if the connection status should be checked once the radio wakes up.
-  bool check_connection_on_radio_wakeup_;
+  bool check_connection_on_radio_wakeup_ = false;
 
   // This is the next ping_id (unique_id) to be sent in PING frame.
-  spdy::SpdyPingId next_ping_id_;
+  spdy::SpdyPingId next_ping_id_ = 1;
 
   // This is the last time we have sent a PING.
   base::TimeTicks last_ping_sent_time_;
@@ -1268,13 +1268,13 @@
   base::TimeTicks last_read_time_;
 
   // This is the length of the last compressed frame.
-  size_t last_compressed_frame_len_;
+  size_t last_compressed_frame_len_ = 0;
 
   // True if there is a CheckPingStatus() task posted on the message loop.
-  bool check_ping_status_pending_;
+  bool check_ping_status_pending_ = false;
 
   // Current send window size.  Zero unless session flow control is turned on.
-  int32_t session_send_window_size_;
+  int32_t session_send_window_size_ = 0;
 
   // Maximum receive window size.  Each time a WINDOW_UPDATE is sent, it
   // restores the receive window size to this value.  Zero unless session flow
@@ -1287,18 +1287,18 @@
   int session_max_queued_capped_frames_;
 
   // Number of active requests which asked for connection status monitoring.
-  int broken_connection_detection_requests_;
+  int broken_connection_detection_requests_ = 0;
 
   // Sum of |session_unacked_recv_window_bytes_| and current receive window
   // size.  Zero unless session flow control is turned on.
   // TODO(bnc): Rename or change semantics so that |window_size_| is actual
   // window size.
-  int32_t session_recv_window_size_;
+  int32_t session_recv_window_size_ = 0;
 
   // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession,
   // and this member keeps count of them until the corresponding WINDOW_UPDATEs
   // are sent.  Zero unless session flow control is turned on.
-  int32_t session_unacked_recv_window_bytes_;
+  int32_t session_unacked_recv_window_bytes_ = 0;
 
   // Time of the last WINDOW_UPDATE for the receive window.
   base::TimeTicks last_recv_window_update_;
@@ -1345,7 +1345,7 @@
   // True if the server has advertised WebSocket support via
   // spdy::SETTINGS_ENABLE_CONNECT_PROTOCOL, see
   // https://tools.ietf.org/html/draft-ietf-httpbis-h2-websockets-00.
-  bool support_websocket_;
+  bool support_websocket_ = false;
 
   // |connection_at_risk_of_loss_time_| is an optimization to avoid sending
   // wasteful preface pings (when we just got some data).
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index da633e2..46766de 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -99,7 +99,6 @@
       ssl_client_context_(ssl_client_context),
       resolver_(resolver),
       quic_supported_versions_(quic_supported_versions),
-      enable_sending_initial_data_(true),
       enable_ping_based_connection_checking_(
           enable_ping_based_connection_checking),
       is_http2_enabled_(is_http2_enabled),
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 3acf8a1..2ba3a0f 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -442,7 +442,7 @@
   const quic::ParsedQuicVersionVector quic_supported_versions_;
 
   // Defaults to true. May be controlled via SpdySessionPoolPeer for tests.
-  bool enable_sending_initial_data_;
+  bool enable_sending_initial_data_ = true;
   bool enable_ping_based_connection_checking_;
 
   const bool is_http2_enabled_;
diff --git a/net/spdy/spdy_session_test_util.cc b/net/spdy/spdy_session_test_util.cc
index 29e1c40..7bd5813 100644
--- a/net/spdy/spdy_session_test_util.cc
+++ b/net/spdy/spdy_session_test_util.cc
@@ -13,7 +13,7 @@
 SpdySessionTestTaskObserver::SpdySessionTestTaskObserver(
     const std::string& file_name,
     const std::string& function_name)
-    : executed_count_(0), file_name_(file_name), function_name_(function_name) {
+    : file_name_(file_name), function_name_(function_name) {
   base::CurrentThread::Get()->AddTaskObserver(this);
 }
 
diff --git a/net/spdy/spdy_session_test_util.h b/net/spdy/spdy_session_test_util.h
index 4b24e29d..fe80eddc 100644
--- a/net/spdy/spdy_session_test_util.h
+++ b/net/spdy/spdy_session_test_util.h
@@ -38,7 +38,7 @@
   uint16_t executed_count() const { return executed_count_; }
 
  private:
-  uint16_t executed_count_;
+  uint16_t executed_count_ = 0;
   std::string file_name_;
   std::string function_name_;
 };
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index b0471f2..160439cc 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -100,27 +100,16 @@
                        const NetworkTrafficAnnotationTag& traffic_annotation,
                        bool detect_broken_connection)
     : type_(type),
-      stream_id_(0),
       url_(url),
       priority_(priority),
-      send_stalled_by_flow_control_(false),
       send_window_size_(initial_send_window_size),
       max_recv_window_size_(max_recv_window_size),
       recv_window_size_(max_recv_window_size),
-      unacked_recv_window_bytes_(0),
       last_recv_window_update_(base::TimeTicks::Now()),
       session_(session),
       delegate_(nullptr),
-      request_headers_valid_(false),
-      pending_send_status_(MORE_DATA_TO_SEND),
       request_time_(base::Time::Now()),
-      response_state_(READY_FOR_HEADERS),
-      io_state_(STATE_IDLE),
       net_log_(net_log),
-      raw_received_bytes_(0),
-      raw_sent_bytes_(0),
-      recv_bytes_(0),
-      write_handler_guard_(false),
       traffic_annotation_(traffic_annotation),
       detect_broken_connection_(detect_broken_connection) {
   CHECK(type_ == SPDY_BIDIRECTIONAL_STREAM ||
diff --git a/net/spdy/spdy_stream.h b/net/spdy/spdy_stream.h
index 4961b13..4cc771a 100644
--- a/net/spdy/spdy_stream.h
+++ b/net/spdy/spdy_stream.h
@@ -474,11 +474,11 @@
 
   const SpdyStreamType type_;
 
-  spdy::SpdyStreamId stream_id_;
+  spdy::SpdyStreamId stream_id_ = 0;
   const GURL url_;
   RequestPriority priority_;
 
-  bool send_stalled_by_flow_control_;
+  bool send_stalled_by_flow_control_ = false;
 
   // Current send window size.
   int32_t send_window_size_;
@@ -496,7 +496,7 @@
   // When bytes are consumed, SpdyIOBuffer destructor calls back to SpdySession,
   // and this member keeps count of them until the corresponding WINDOW_UPDATEs
   // are sent.
-  int32_t unacked_recv_window_bytes_;
+  int32_t unacked_recv_window_bytes_ = 0;
 
   // Time of the last WINDOW_UPDATE for the receive window
   base::TimeTicks last_recv_window_update_;
@@ -507,13 +507,13 @@
   raw_ptr<SpdyStream::Delegate> delegate_;
 
   // The headers for the request to send.
-  bool request_headers_valid_;
+  bool request_headers_valid_ = false;
   spdy::Http2HeaderBlock request_headers_;
 
   // Data waiting to be sent, and the close state of the local endpoint
   // after the data is fully written.
   scoped_refptr<DrainableIOBuffer> pending_send_data_;
-  SpdySendStatus pending_send_status_;
+  SpdySendStatus pending_send_status_ = MORE_DATA_TO_SEND;
 
   // Data waiting to be received, and the close state of the remote endpoint
   // after the data is fully read. Specifically, data received before the
@@ -526,10 +526,10 @@
   base::Time request_time_;
 
   spdy::Http2HeaderBlock response_headers_;
-  ResponseState response_state_;
+  ResponseState response_state_ = READY_FOR_HEADERS;
   base::Time response_time_;
 
-  State io_state_;
+  State io_state_ = STATE_IDLE;
 
   NetLogWithSource net_log_;
 
@@ -553,19 +553,19 @@
 
   // Number of bytes that have been received on this stream, including frame
   // overhead and headers.
-  int64_t raw_received_bytes_;
+  int64_t raw_received_bytes_ = 0;
   // Number of bytes that have been sent on this stream, including frame
   // overhead and headers.
-  int64_t raw_sent_bytes_;
+  int64_t raw_sent_bytes_ = 0;
 
   // Number of data bytes that have been received on this stream, not including
   // frame overhead. Note that this does not count headers.
-  int recv_bytes_;
+  int recv_bytes_ = 0;
 
   // Guards calls of delegate write handlers ensuring |this| is not destroyed.
   // TODO(jgraettinger): Consider removing after crbug.com/35511 is tracked
   // down.
-  bool write_handler_guard_;
+  bool write_handler_guard_ = false;
 
   const NetworkTrafficAnnotationTag traffic_annotation_;
 
diff --git a/net/spdy/spdy_stream_test_util.cc b/net/spdy/spdy_stream_test_util.cc
index 50bd5e7..160f385 100644
--- a/net/spdy/spdy_stream_test_util.cc
+++ b/net/spdy/spdy_stream_test_util.cc
@@ -51,12 +51,8 @@
   return NetLogSource();
 }
 
-StreamDelegateBase::StreamDelegateBase(
-    const base::WeakPtr<SpdyStream>& stream)
-    : stream_(stream),
-      stream_id_(0),
-      send_headers_completed_(false) {
-}
+StreamDelegateBase::StreamDelegateBase(const base::WeakPtr<SpdyStream>& stream)
+    : stream_(stream) {}
 
 StreamDelegateBase::~StreamDelegateBase() = default;
 
diff --git a/net/spdy/spdy_stream_test_util.h b/net/spdy/spdy_stream_test_util.h
index 711b85f..c560c3d 100644
--- a/net/spdy/spdy_stream_test_util.h
+++ b/net/spdy/spdy_stream_test_util.h
@@ -100,9 +100,9 @@
 
  private:
   base::WeakPtr<SpdyStream> stream_;
-  spdy::SpdyStreamId stream_id_;
+  spdy::SpdyStreamId stream_id_ = 0;
   TestCompletionCallback callback_;
-  bool send_headers_completed_;
+  bool send_headers_completed_ = false;
   std::vector<spdy::Http2HeaderBlock> early_hints_;
   spdy::Http2HeaderBlock response_headers_;
   SpdyReadQueue received_data_queue_;
diff --git a/net/spdy/spdy_stream_unittest.cc b/net/spdy/spdy_stream_unittest.cc
index fc3b988..59f4da8 100644
--- a/net/spdy/spdy_stream_unittest.cc
+++ b/net/spdy/spdy_stream_unittest.cc
@@ -87,7 +87,6 @@
       : WithTaskEnvironment(time_source),
         url_(kDefaultUrl),
         session_(SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
-        offset_(0),
         ssl_(SYNCHRONOUS, OK) {}
 
   ~SpdyStreamTest() override = default;
@@ -176,7 +175,7 @@
   // Used by Add{Read,Write}() above.
   std::vector<MockWrite> writes_;
   std::vector<MockRead> reads_;
-  int offset_;
+  int offset_ = 0;
   SSLSocketDataProvider ssl_;
 };
 
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 8716214..f7f3305 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -182,7 +182,7 @@
 
 class PriorityGetter : public BufferedSpdyFramerVisitorInterface {
  public:
-  PriorityGetter() : priority_(0) {}
+  PriorityGetter() = default;
   ~PriorityGetter() override = default;
 
   spdy::SpdyPriority priority() const { return priority_; }
@@ -236,7 +236,7 @@
   }
 
  private:
-  spdy::SpdyPriority priority_;
+  spdy::SpdyPriority priority_ = 0;
 };
 
 }  // namespace
diff --git a/net/spdy/spdy_write_queue.cc b/net/spdy/spdy_write_queue.cc
index 3dba92ff..cc9517d5 100644
--- a/net/spdy/spdy_write_queue.cc
+++ b/net/spdy/spdy_write_queue.cc
@@ -44,7 +44,7 @@
 SpdyWriteQueue::PendingWrite& SpdyWriteQueue::PendingWrite::operator=(
     PendingWrite&& other) = default;
 
-SpdyWriteQueue::SpdyWriteQueue() : removing_writes_(false) {}
+SpdyWriteQueue::SpdyWriteQueue() = default;
 
 SpdyWriteQueue::~SpdyWriteQueue() {
   DCHECK_GE(num_queued_capped_frames_, 0);
diff --git a/net/spdy/spdy_write_queue.h b/net/spdy/spdy_write_queue.h
index e3987b7..b353f175 100644
--- a/net/spdy/spdy_write_queue.h
+++ b/net/spdy/spdy_write_queue.h
@@ -106,7 +106,7 @@
     ~PendingWrite();
   };
 
-  bool removing_writes_;
+  bool removing_writes_ = false;
 
   // Number of currently queued capped frames including all priorities.
   int num_queued_capped_frames_ = 0;
diff --git a/net/ssl/openssl_ssl_util.cc b/net/ssl/openssl_ssl_util.cc
index c5b7bfb..2e8e2cd 100644
--- a/net/ssl/openssl_ssl_util.cc
+++ b/net/ssl/openssl_ssl_util.cc
@@ -24,10 +24,7 @@
 
 namespace net {
 
-SslSetClearMask::SslSetClearMask()
-    : set_mask(0),
-      clear_mask(0) {
-}
+SslSetClearMask::SslSetClearMask() = default;
 
 void SslSetClearMask::ConfigureFlag(long flag, bool state) {
   (state ? set_mask : clear_mask) |= flag;
diff --git a/net/ssl/openssl_ssl_util.h b/net/ssl/openssl_ssl_util.h
index 18c7040..5cce274 100644
--- a/net/ssl/openssl_ssl_util.h
+++ b/net/ssl/openssl_ssl_util.h
@@ -34,8 +34,8 @@
   SslSetClearMask();
   void ConfigureFlag(long flag, bool state);
 
-  long set_mask;
-  long clear_mask;
+  long set_mask = 0;
+  long clear_mask = 0;
 };
 
 // Converts an OpenSSL error code into a net error code, walking the OpenSSL
@@ -50,11 +50,11 @@
 
 // Helper struct to store information about an OpenSSL error stack entry.
 struct OpenSSLErrorInfo {
-  OpenSSLErrorInfo() : error_code(0), file(nullptr), line(0) {}
+  OpenSSLErrorInfo() = default;
 
-  uint32_t error_code;
-  const char* file;
-  int line;
+  uint32_t error_code = 0;
+  const char* file = nullptr;
+  int line = 0;
 };
 
 // Converts an OpenSSL error code into a net error code, walking the OpenSSL
diff --git a/net/ssl/ssl_cert_request_info.cc b/net/ssl/ssl_cert_request_info.cc
index 2ad30cdc..39f6d8f 100644
--- a/net/ssl/ssl_cert_request_info.cc
+++ b/net/ssl/ssl_cert_request_info.cc
@@ -8,8 +8,7 @@
 
 namespace net {
 
-SSLCertRequestInfo::SSLCertRequestInfo() : is_proxy(false) {
-}
+SSLCertRequestInfo::SSLCertRequestInfo() = default;
 
 void SSLCertRequestInfo::Reset() {
   host_and_port = HostPortPair();
diff --git a/net/ssl/ssl_cert_request_info.h b/net/ssl/ssl_cert_request_info.h
index 3f0443e..9eaffe6 100644
--- a/net/ssl/ssl_cert_request_info.h
+++ b/net/ssl/ssl_cert_request_info.h
@@ -44,7 +44,7 @@
 
   // True if the server that issues this request was the HTTPS proxy used in
   // the request.  False, if the server was the origin server.
-  bool is_proxy;
+  bool is_proxy = false;
 
   // List of DER-encoded X.509 DistinguishedName of certificate authorities
   // allowed by the server.
diff --git a/net/ssl/ssl_client_session_cache.cc b/net/ssl/ssl_client_session_cache.cc
index 0fecc48..dab00af 100644
--- a/net/ssl/ssl_client_session_cache.cc
+++ b/net/ssl/ssl_client_session_cache.cc
@@ -44,8 +44,7 @@
 SSLClientSessionCache::SSLClientSessionCache(const Config& config)
     : clock_(base::DefaultClock::GetInstance()),
       config_(config),
-      cache_(config.max_entries),
-      lookups_since_flush_(0) {
+      cache_(config.max_entries) {
   memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>(
       FROM_HERE, base::BindRepeating(&SSLClientSessionCache::OnMemoryPressure,
                                      base::Unretained(this)));
diff --git a/net/ssl/ssl_client_session_cache.h b/net/ssl/ssl_client_session_cache.h
index 24655c13..271427e 100644
--- a/net/ssl/ssl_client_session_cache.h
+++ b/net/ssl/ssl_client_session_cache.h
@@ -121,7 +121,7 @@
   raw_ptr<base::Clock> clock_;
   Config config_;
   base::LRUCache<Key, Entry> cache_;
-  size_t lookups_since_flush_;
+  size_t lookups_since_flush_ = 0;
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 };
 
diff --git a/net/ssl/ssl_server_config.cc b/net/ssl/ssl_server_config.cc
index 1002210..425d326b 100644
--- a/net/ssl/ssl_server_config.cc
+++ b/net/ssl/ssl_server_config.cc
@@ -13,9 +13,6 @@
 SSLServerConfig::SSLServerConfig()
     : version_min(kDefaultSSLVersionMin),
       version_max(kDefaultSSLVersionMax),
-      early_data_enabled(false),
-      require_ecdhe(false),
-      client_cert_type(NO_CLIENT_CERT),
       client_cert_verifier(nullptr) {}
 
 SSLServerConfig::SSLServerConfig(const SSLServerConfig& other) = default;
diff --git a/net/ssl/ssl_server_config.h b/net/ssl/ssl_server_config.h
index 43d0368..520a8642 100644
--- a/net/ssl/ssl_server_config.h
+++ b/net/ssl/ssl_server_config.h
@@ -45,7 +45,7 @@
 
   // Whether early data is enabled on this connection. The caller is obligated
   // to reject early data that is non-safe to be replayed.
-  bool early_data_enabled;
+  bool early_data_enabled = false;
 
   // Presorted list of cipher suites which should be explicitly prevented from
   // being used in addition to those disabled by the net built-in policy.
@@ -71,7 +71,7 @@
   std::vector<uint16_t> disabled_cipher_suites;
 
   // If true, causes only ECDHE cipher suites to be enabled.
-  bool require_ecdhe;
+  bool require_ecdhe = false;
 
   // cipher_suite_for_testing, if set, causes the server to only support the
   // specified cipher suite in TLS 1.2 and below. This should only be used in
@@ -88,7 +88,7 @@
   std::vector<int> curves_for_testing;
 
   // Sets the requirement for client certificates during handshake.
-  ClientCertType client_cert_type;
+  ClientCertType client_cert_type = NO_CLIENT_CERT;
 
   // List of DER-encoded X.509 DistinguishedName of certificate authorities
   // to be included in the CertificateRequest handshake message,
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index b37e23bd..bd61f6a 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -50,10 +50,7 @@
     : public net::test_server::EmbeddedTestServerConnectionListener {
  public:
   TestConnectionListener()
-      : socket_accepted_count_(0),
-        did_read_from_socket_(false),
-        did_get_socket_on_complete_(false),
-        task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
+      : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
 
   TestConnectionListener(const TestConnectionListener&) = delete;
   TestConnectionListener& operator=(const TestConnectionListener&) = delete;
@@ -104,9 +101,9 @@
   }
 
  private:
-  size_t socket_accepted_count_;
-  bool did_read_from_socket_;
-  bool did_get_socket_on_complete_;
+  size_t socket_accepted_count_ = 0;
+  bool did_read_from_socket_ = false;
+  bool did_get_socket_on_complete_ = false;
 
   base::RunLoop accept_loop_;
   base::RunLoop complete_loop_;
diff --git a/net/test/embedded_test_server/http_request.cc b/net/test/embedded_test_server/http_request.cc
index efb8a7e..691a4b4 100644
--- a/net/test/embedded_test_server/http_request.cc
+++ b/net/test/embedded_test_server/http_request.cc
@@ -30,9 +30,7 @@
 
 }  // namespace
 
-HttpRequest::HttpRequest() : method(METHOD_UNKNOWN),
-                             has_content(false) {
-}
+HttpRequest::HttpRequest() = default;
 
 HttpRequest::HttpRequest(const HttpRequest& other) = default;
 
@@ -45,10 +43,7 @@
 }
 
 HttpRequestParser::HttpRequestParser()
-    : http_request_(std::make_unique<HttpRequest>()),
-      buffer_position_(0),
-      state_(STATE_HEADERS),
-      declared_content_length_(0) {}
+    : http_request_(std::make_unique<HttpRequest>()) {}
 
 HttpRequestParser::~HttpRequestParser() = default;
 
diff --git a/net/test/embedded_test_server/http_request.h b/net/test/embedded_test_server/http_request.h
index 8ddde91..91cdaed 100644
--- a/net/test/embedded_test_server/http_request.h
+++ b/net/test/embedded_test_server/http_request.h
@@ -61,12 +61,12 @@
 
   std::string relative_url;  // Starts with '/'. Example: "/test?query=foo"
   GURL base_url;
-  HttpMethod method;
+  HttpMethod method = METHOD_UNKNOWN;
   std::string method_string;
   std::string all_headers;
   HeaderMap headers;
   std::string content;
-  bool has_content;
+  bool has_content = false;
   absl::optional<SSLInfo> ssl_info;
 };
 
@@ -135,10 +135,10 @@
 
   std::unique_ptr<HttpRequest> http_request_;
   std::string buffer_;
-  size_t buffer_position_;  // Current position in the internal buffer.
-  State state_;
+  size_t buffer_position_ = 0;  // Current position in the internal buffer.
+  State state_ = STATE_HEADERS;
   // Content length of the request currently being parsed.
-  size_t declared_content_length_;
+  size_t declared_content_length_ = 0;
 
   std::unique_ptr<HttpChunkedDecoder> chunked_decoder_;
 };
diff --git a/net/test/embedded_test_server/http_response.cc b/net/test/embedded_test_server/http_response.cc
index 1aafb2be1..cc38408 100644
--- a/net/test/embedded_test_server/http_response.cc
+++ b/net/test/embedded_test_server/http_response.cc
@@ -58,7 +58,7 @@
   headers_.append(base::StringPrintf("%s\r\n", key_value_pair.c_str()));
 }
 
-BasicHttpResponse::BasicHttpResponse() : code_(HTTP_OK) {}
+BasicHttpResponse::BasicHttpResponse() = default;
 
 BasicHttpResponse::~BasicHttpResponse() = default;
 
diff --git a/net/test/embedded_test_server/http_response.h b/net/test/embedded_test_server/http_response.h
index f352100..de2ffe0 100644
--- a/net/test/embedded_test_server/http_response.h
+++ b/net/test/embedded_test_server/http_response.h
@@ -126,7 +126,7 @@
   void SendResponse(base::WeakPtr<HttpResponseDelegate> delegate) override;
 
  private:
-  HttpStatusCode code_;
+  HttpStatusCode code_ = HTTP_OK;
   absl::optional<std::string> reason_;
   std::string content_;
   std::string content_type_;
diff --git a/net/test/url_request/url_request_hanging_read_job.cc b/net/test/url_request/url_request_hanging_read_job.cc
index 60008a0d..b03430a 100644
--- a/net/test/url_request/url_request_hanging_read_job.cc
+++ b/net/test/url_request/url_request_hanging_read_job.cc
@@ -44,9 +44,7 @@
 }  // namespace
 
 URLRequestHangingReadJob::URLRequestHangingReadJob(URLRequest* request)
-    : URLRequestJob(request),
-      // non-zero content-length
-      content_length_(10) {}
+    : URLRequestJob(request) {}
 
 URLRequestHangingReadJob::~URLRequestHangingReadJob() = default;
 
diff --git a/net/test/url_request/url_request_hanging_read_job.h b/net/test/url_request/url_request_hanging_read_job.h
index 938e31b..3350e55 100644
--- a/net/test/url_request/url_request_hanging_read_job.h
+++ b/net/test/url_request/url_request_hanging_read_job.h
@@ -37,7 +37,7 @@
 
   void StartAsync();
 
-  const int content_length_;
+  const int content_length_ = 10;  // non-zero content-length
   base::WeakPtrFactory<URLRequestHangingReadJob> weak_factory_{this};
 };
 
diff --git a/net/test/url_request/url_request_mock_data_job.cc b/net/test/url_request/url_request_mock_data_job.cc
index 9e2d8c3c4..72cbaeb 100644
--- a/net/test/url_request/url_request_mock_data_job.cc
+++ b/net/test/url_request/url_request_mock_data_job.cc
@@ -100,7 +100,6 @@
                                              int data_repeat_count,
                                              bool request_client_certificate)
     : URLRequestJob(request),
-      data_offset_(0),
       request_client_certificate_(request_client_certificate) {
   DCHECK_GT(data_repeat_count, 0);
   for (int i = 0; i < data_repeat_count; ++i) {
diff --git a/net/test/url_request/url_request_mock_data_job.h b/net/test/url_request/url_request_mock_data_job.h
index f2789e1..1d207bc3 100644
--- a/net/test/url_request/url_request_mock_data_job.h
+++ b/net/test/url_request/url_request_mock_data_job.h
@@ -68,7 +68,7 @@
 
   absl::optional<std::string> headers_;
   std::string data_;
-  size_t data_offset_;
+  size_t data_offset_ = 0;
   bool request_client_certificate_;
   base::WeakPtrFactory<URLRequestMockDataJob> weak_factory_{this};
 };
diff --git a/net/test/url_request/url_request_test_job_backed_by_file.cc b/net/test/url_request/url_request_test_job_backed_by_file.cc
index fac551a..8e906a1 100644
--- a/net/test/url_request/url_request_test_job_backed_by_file.cc
+++ b/net/test/url_request/url_request_test_job_backed_by_file.cc
@@ -45,11 +45,7 @@
 
 namespace net {
 
-URLRequestTestJobBackedByFile::FileMetaInfo::FileMetaInfo()
-    : file_size(0),
-      mime_type_result(false),
-      file_exists(false),
-      is_directory(false) {}
+URLRequestTestJobBackedByFile::FileMetaInfo::FileMetaInfo() = default;
 
 URLRequestTestJobBackedByFile::URLRequestTestJobBackedByFile(
     URLRequest* request,
@@ -58,9 +54,7 @@
     : URLRequestJob(request),
       file_path_(file_path),
       stream_(new FileStream(file_task_runner)),
-      file_task_runner_(file_task_runner),
-      remaining_bytes_(0),
-      range_parse_result_(OK) {}
+      file_task_runner_(file_task_runner) {}
 
 void URLRequestTestJobBackedByFile::Start() {
   FileMetaInfo* meta_info = new FileMetaInfo();
diff --git a/net/test/url_request/url_request_test_job_backed_by_file.h b/net/test/url_request/url_request_test_job_backed_by_file.h
index 668120c9..a850f88 100644
--- a/net/test/url_request/url_request_test_job_backed_by_file.h
+++ b/net/test/url_request/url_request_test_job_backed_by_file.h
@@ -89,16 +89,16 @@
     FileMetaInfo();
 
     // Size of the file.
-    int64_t file_size;
+    int64_t file_size = 0;
     // Mime type associated with the file.
     std::string mime_type;
     // Result returned from GetMimeTypeFromFile(), i.e. flag showing whether
     // obtaining of the mime type was successful.
-    bool mime_type_result;
+    bool mime_type_result = false;
     // Flag showing whether the file exists.
-    bool file_exists;
+    bool file_exists = false;
     // Flag showing whether the file name actually refers to a directory.
-    bool is_directory;
+    bool is_directory = false;
     // Absolute path of the file (i.e. symbolic link is resolved).
     base::FilePath absolute_path;
   };
@@ -126,10 +126,10 @@
 
   std::vector<HttpByteRange> byte_ranges_;
   HttpByteRange byte_range_;
-  int64_t remaining_bytes_;
+  int64_t remaining_bytes_ = 0;
   bool serve_mime_type_as_content_type_ = false;
 
-  Error range_parse_result_;
+  Error range_parse_result_ = OK;
 
   base::WeakPtrFactory<URLRequestTestJobBackedByFile> weak_ptr_factory_{this};
 };
diff --git a/net/tools/cachetool/cachetool.cc b/net/tools/cachetool/cachetool.cc
index d6f0f455..6b7634e 100644
--- a/net/tools/cachetool/cachetool.cc
+++ b/net/tools/cachetool/cachetool.cc
@@ -85,7 +85,7 @@
 class CommandMarshal {
  public:
   explicit CommandMarshal(Backend* cache_backend)
-      : command_failed_(false), cache_backend_(cache_backend) {}
+      : cache_backend_(cache_backend) {}
   virtual ~CommandMarshal() = default;
 
   // Reads the next command's name to execute.
@@ -137,7 +137,7 @@
   Backend* cache_backend() { return cache_backend_; }
 
  protected:
-  bool command_failed_;
+  bool command_failed_ = false;
   Backend* const cache_backend_;
 };
 
@@ -146,7 +146,7 @@
  public:
   ProgramArgumentCommandMarshal(Backend* cache_backend,
                                 base::CommandLine::StringVector args)
-      : CommandMarshal(cache_backend), command_line_args_(args), args_id_(0) {}
+      : CommandMarshal(cache_backend), command_line_args_(args) {}
 
   // Implements CommandMarshal.
   std::string ReadCommandName() override {
@@ -220,7 +220,7 @@
 
  private:
   const base::CommandLine::StringVector command_line_args_;
-  size_t args_id_;
+  size_t args_id_ = 0;
 };
 
 // Online command input/output that receives pickled commands from stdin and
diff --git a/net/tools/dump_cache/dump_files.cc b/net/tools/dump_cache/dump_files.cc
index 009b0e8..34253344 100644
--- a/net/tools/dump_cache/dump_files.cc
+++ b/net/tools/dump_cache/dump_files.cc
@@ -160,11 +160,7 @@
 class CacheDumper {
  public:
   explicit CacheDumper(const base::FilePath& path)
-      : path_(path),
-        block_files_(path),
-        index_(nullptr),
-        current_hash_(0),
-        next_addr_(0) {}
+      : path_(path), block_files_(path) {}
 
   CacheDumper(const CacheDumper&) = delete;
   CacheDumper& operator=(const CacheDumper&) = delete;
@@ -187,9 +183,9 @@
   base::FilePath path_;
   disk_cache::BlockFiles block_files_;
   scoped_refptr<disk_cache::MappedFile> index_file_;
-  disk_cache::Index* index_;
-  int current_hash_;
-  disk_cache::CacheAddr next_addr_;
+  disk_cache::Index* index_ = nullptr;
+  int current_hash_ = 0;
+  disk_cache::CacheAddr next_addr_ = 0;
   std::set<disk_cache::CacheAddr> dumped_entries_;
 };
 
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.cc b/net/tools/quic/quic_client_message_loop_network_helper.cc
index 61842efb..4bd223f8 100644
--- a/net/tools/quic/quic_client_message_loop_network_helper.cc
+++ b/net/tools/quic/quic_client_message_loop_network_helper.cc
@@ -37,7 +37,7 @@
 QuicClientMessageLooplNetworkHelper::QuicClientMessageLooplNetworkHelper(
     quic::QuicChromiumClock* clock,
     quic::QuicClientBase* client)
-    : packet_reader_started_(false), clock_(clock), client_(client) {}
+    : clock_(clock), client_(client) {}
 
 QuicClientMessageLooplNetworkHelper::~QuicClientMessageLooplNetworkHelper() =
     default;
diff --git a/net/tools/quic/quic_client_message_loop_network_helper.h b/net/tools/quic/quic_client_message_loop_network_helper.h
index 23309bc..e11e4c5 100644
--- a/net/tools/quic/quic_client_message_loop_network_helper.h
+++ b/net/tools/quic/quic_client_message_loop_network_helper.h
@@ -70,7 +70,7 @@
 
   std::unique_ptr<QuicChromiumPacketReader> packet_reader_;
 
-  bool packet_reader_started_;
+  bool packet_reader_started_ = false;
 
   quic::QuicChromiumClock* clock_;
   quic::QuicClientBase* client_;
diff --git a/net/tools/quic/quic_simple_client.cc b/net/tools/quic/quic_simple_client.cc
index b10c9e8a..e355be1 100644
--- a/net/tools/quic/quic_simple_client.cc
+++ b/net/tools/quic/quic_simple_client.cc
@@ -48,8 +48,7 @@
           base::WrapUnique(
               new QuicClientMessageLooplNetworkHelper(&clock_, this)),
           std::move(proof_verifier),
-          nullptr),
-      initialized_(false) {
+          nullptr) {
   set_server_address(server_address);
 }
 
diff --git a/net/tools/quic/quic_simple_client.h b/net/tools/quic/quic_simple_client.h
index 092c70d..01f8f4cc 100644
--- a/net/tools/quic/quic_simple_client.h
+++ b/net/tools/quic/quic_simple_client.h
@@ -61,7 +61,7 @@
   quic::QuicChromiumClock clock_;
 
   // Tracks if the client is initialized to connect.
-  bool initialized_;
+  bool initialized_ = false;
 
   base::WeakPtrFactory<QuicSimpleClient> weak_factory_{this};
 };
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index 512fd4d..7d993f9 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -60,8 +60,6 @@
                      quic::QuicRandom::GetInstance(),
                      std::move(proof_source),
                      quic::KeyExchangeSource::Default()),
-      read_pending_(false),
-      synchronous_read_count_(0),
       read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)),
       quic_simple_server_backend_(quic_simple_server_backend) {
   DCHECK(quic_simple_server_backend);
diff --git a/net/tools/quic/quic_simple_server.h b/net/tools/quic/quic_simple_server.h
index 4a31038f..c6f6f48 100644
--- a/net/tools/quic/quic_simple_server.h
+++ b/net/tools/quic/quic_simple_server.h
@@ -109,11 +109,11 @@
 
   // Keeps track of whether a read is currently in flight, after which
   // OnReadComplete will be called.
-  bool read_pending_;
+  bool read_pending_ = false;
 
   // The number of iterations of the read loop that have completed synchronously
   // and without posting a new task to the message loop.
-  int synchronous_read_count_;
+  int synchronous_read_count_ = 0;
 
   // The target buffer of the current read.
   scoped_refptr<IOBufferWithSize> read_buffer_;
diff --git a/net/tools/quic/quic_simple_server_packet_writer.cc b/net/tools/quic/quic_simple_server_packet_writer.cc
index cee2342..8d1349804 100644
--- a/net/tools/quic/quic_simple_server_packet_writer.cc
+++ b/net/tools/quic/quic_simple_server_packet_writer.cc
@@ -21,7 +21,7 @@
 QuicSimpleServerPacketWriter::QuicSimpleServerPacketWriter(
     UDPServerSocket* socket,
     quic::QuicDispatcher* dispatcher)
-    : socket_(socket), dispatcher_(dispatcher), write_blocked_(false) {}
+    : socket_(socket), dispatcher_(dispatcher) {}
 
 QuicSimpleServerPacketWriter::~QuicSimpleServerPacketWriter() = default;
 
diff --git a/net/tools/quic/quic_simple_server_packet_writer.h b/net/tools/quic/quic_simple_server_packet_writer.h
index f5130586..667980a 100644
--- a/net/tools/quic/quic_simple_server_packet_writer.h
+++ b/net/tools/quic/quic_simple_server_packet_writer.h
@@ -65,7 +65,7 @@
   quic::QuicDispatcher* dispatcher_;
 
   // Whether a write is currently in flight.
-  bool write_blocked_;
+  bool write_blocked_ = false;
 
   base::WeakPtrFactory<QuicSimpleServerPacketWriter> weak_factory_{this};
 };
diff --git a/net/tools/stress_cache/stress_cache.cc b/net/tools/stress_cache/stress_cache.cc
index c6eb68a..64187c80 100644
--- a/net/tools/stress_cache/stress_cache.cc
+++ b/net/tools/stress_cache/stress_cache.cc
@@ -124,7 +124,7 @@
 // closed or deleted.
 class EntryWrapper {
  public:
-  EntryWrapper() : entry_(nullptr), state_(NONE) {
+  EntryWrapper() {
     buffer_ = base::MakeRefCounted<net::IOBuffer>(kBufferSize);
     memset(buffer_->data(), 'k', kBufferSize);
   }
@@ -143,19 +143,19 @@
   void OnDeleteDone(int result);
   void DoIdle();
 
-  disk_cache::Entry* entry_;
-  Operation state_;
+  disk_cache::Entry* entry_ = nullptr;
+  Operation state_ = NONE;
   scoped_refptr<net::IOBuffer> buffer_;
 };
 
 // The data that the main thread is working on.
 struct Data {
-  Data() : pendig_operations(0), writes(0), iteration(0), cache(nullptr) {}
+  Data() = default;
 
-  int pendig_operations;  // Counter of simultaneous operations.
-  int writes;             // How many writes since this iteration started.
-  int iteration;          // The iteration (number of crashes).
-  disk_cache::BackendImpl* cache;
+  int pendig_operations = 0;  // Counter of simultaneous operations.
+  int writes = 0;             // How many writes since this iteration started.
+  int iteration = 0;          // The iteration (number of crashes).
+  disk_cache::BackendImpl* cache = nullptr;
   std::string keys[kNumKeys];
   EntryWrapper entries[kNumEntries];
 };
diff --git a/net/url_request/http_with_dns_over_https_unittest.cc b/net/url_request/http_with_dns_over_https_unittest.cc
index 0f8c20c6..43c94da 100644
--- a/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/net/url_request/http_with_dns_over_https_unittest.cc
@@ -64,8 +64,7 @@
 
 class TestHostResolverProc : public HostResolverProc {
  public:
-  TestHostResolverProc()
-      : HostResolverProc(nullptr), insecure_queries_served_(0) {}
+  TestHostResolverProc() : HostResolverProc(nullptr) {}
 
   int Resolve(const std::string& hostname,
               AddressFamily address_family,
@@ -80,8 +79,8 @@
   uint32_t insecure_queries_served() { return insecure_queries_served_; }
 
  private:
-  ~TestHostResolverProc() override {}
-  uint32_t insecure_queries_served_;
+  ~TestHostResolverProc() override = default;
+  uint32_t insecure_queries_served_ = 0;
 };
 
 // Runs and waits for the DoH probe to complete in automatic mode. The resolver
@@ -223,7 +222,7 @@
 class TestHttpDelegate : public HttpStreamRequest::Delegate {
  public:
   explicit TestHttpDelegate(base::RunLoop* loop) : loop_(loop) {}
-  ~TestHttpDelegate() override {}
+  ~TestHttpDelegate() override = default;
   void OnStreamReady(const SSLConfig& used_ssl_config,
                      const ProxyInfo& used_proxy_info,
                      std::unique_ptr<HttpStream> stream) override {
diff --git a/net/url_request/redirect_info.cc b/net/url_request/redirect_info.cc
index 940027e5..7cb82bb 100644
--- a/net/url_request/redirect_info.cc
+++ b/net/url_request/redirect_info.cc
@@ -99,12 +99,7 @@
 
 }  // namespace
 
-RedirectInfo::RedirectInfo()
-    : status_code(-1),
-      insecure_scheme_was_upgraded(false),
-      is_signed_exchange_fallback_redirect(false),
-      new_referrer_policy(
-          ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE) {}
+RedirectInfo::RedirectInfo() = default;
 
 RedirectInfo::RedirectInfo(const RedirectInfo& other) = default;
 
diff --git a/net/url_request/redirect_info.h b/net/url_request/redirect_info.h
index 7685caa..14a2672 100644
--- a/net/url_request/redirect_info.h
+++ b/net/url_request/redirect_info.h
@@ -60,7 +60,7 @@
   // The status code for the redirect response. This is almost redundant with
   // the response headers, but some URLRequestJobs emit redirects without
   // headers.
-  int status_code;
+  int status_code = -1;
 
   // The new request method. Depending on the response code, the request method
   // may change.
@@ -77,14 +77,15 @@
 
   // True if this redirect was upgraded to HTTPS due to the
   // upgrade-insecure-requests policy.
-  bool insecure_scheme_was_upgraded;
+  bool insecure_scheme_was_upgraded = false;
 
   // True if this is a redirect from Signed Exchange to its fallback URL.
-  bool is_signed_exchange_fallback_redirect;
+  bool is_signed_exchange_fallback_redirect = false;
 
   // The new referrer policy that should be obeyed if there are
   // subsequent redirects.
-  ReferrerPolicy new_referrer_policy;
+  ReferrerPolicy new_referrer_policy =
+      ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
 };
 
 }  // namespace net
diff --git a/net/url_request/report_sender_unittest.cc b/net/url_request/report_sender_unittest.cc
index 49d2695..e1f5d81 100644
--- a/net/url_request/report_sender_unittest.cc
+++ b/net/url_request/report_sender_unittest.cc
@@ -123,8 +123,7 @@
  public:
   TestReportSenderNetworkDelegate()
       : url_request_destroyed_callback_(base::DoNothing()),
-        all_url_requests_destroyed_callback_(base::DoNothing()),
-        num_requests_(0) {}
+        all_url_requests_destroyed_callback_(base::DoNothing()) {}
 
   TestReportSenderNetworkDelegate(const TestReportSenderNetworkDelegate&) =
       delete;
@@ -195,7 +194,7 @@
  private:
   base::RepeatingClosure url_request_destroyed_callback_;
   base::RepeatingClosure all_url_requests_destroyed_callback_;
-  size_t num_requests_;
+  size_t num_requests_ = 0;
   GURL expect_url_;
   std::set<std::string> expect_reports_;
   std::string expected_content_type_;
diff --git a/net/url_request/test_url_fetcher_factory.cc b/net/url_request/test_url_fetcher_factory.cc
index 8e03d6c..321e1013 100644
--- a/net/url_request/test_url_fetcher_factory.cc
+++ b/net/url_request/test_url_fetcher_factory.cc
@@ -42,18 +42,7 @@
 }
 
 TestURLFetcher::TestURLFetcher(int id, const GURL& url, URLFetcherDelegate* d)
-    : id_(id),
-      original_url_(url),
-      delegate_(d),
-      delegate_for_tests_(nullptr),
-      did_receive_last_chunk_(false),
-      fake_load_flags_(0),
-      fake_response_code_(-1),
-      fake_response_destination_(STRING),
-      write_response_file_(false),
-      fake_was_cached_(false),
-      fake_response_bytes_(0),
-      fake_max_retries_(0) {
+    : id_(id), original_url_(url), delegate_(d), delegate_for_tests_(nullptr) {
   CHECK(original_url_.is_valid());
 }
 
diff --git a/net/url_request/test_url_fetcher_factory.h b/net/url_request/test_url_fetcher_factory.h
index 7a3877f..c75f208 100644
--- a/net/url_request/test_url_fetcher_factory.h
+++ b/net/url_request/test_url_fetcher_factory.h
@@ -218,26 +218,26 @@
   std::string upload_data_;
   base::FilePath upload_file_path_;
   std::list<std::string> chunks_;
-  bool did_receive_last_chunk_;
+  bool did_receive_last_chunk_ = false;
 
   // User can use set_* methods to provide values returned by getters.
   // Setting the real values is not possible, because the real class
   // has no setters. The data is a private member of a class defined
   // in a .cc file, so we can't get at it with friendship.
-  int fake_load_flags_;
+  int fake_load_flags_ = 0;
   GURL fake_url_;
   Error fake_error_;
-  int fake_response_code_;
-  ResponseDestinationType fake_response_destination_;
+  int fake_response_code_ = -1;
+  ResponseDestinationType fake_response_destination_ = STRING;
   std::string fake_response_string_;
   base::FilePath fake_response_file_path_;
-  bool write_response_file_;
+  bool write_response_file_ = false;
   ProxyServer fake_proxy_server_;
-  bool fake_was_cached_;
-  int64_t fake_response_bytes_;
+  bool fake_was_cached_ = false;
+  int64_t fake_response_bytes_ = 0;
   scoped_refptr<HttpResponseHeaders> fake_response_headers_;
   HttpRequestHeaders fake_extra_request_headers_;
-  int fake_max_retries_;
+  int fake_max_retries_ = 0;
   std::unique_ptr<URLFetcherResponseWriter> response_writer_;
 };
 
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc
index b9991d11..22b58be 100644
--- a/net/url_request/url_fetcher_core.cc
+++ b/net/url_request/url_fetcher_core.cc
@@ -83,30 +83,8 @@
       request_type_(request_type),
       delegate_(d),
       delegate_task_runner_(base::SequencedTaskRunnerHandle::Get()),
-      load_flags_(LOAD_NORMAL),
       allow_credentials_(absl::nullopt),
-      response_code_(URLFetcher::RESPONSE_CODE_INVALID),
       url_request_data_key_(nullptr),
-      was_cached_(false),
-      received_response_content_length_(0),
-      total_received_bytes_(0),
-      upload_content_set_(false),
-      upload_range_offset_(0),
-      upload_range_length_(0),
-      referrer_policy_(
-          ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
-      is_chunked_upload_(false),
-      was_cancelled_(false),
-      stop_on_redirect_(false),
-      stopped_on_redirect_(false),
-      automatically_retry_on_5xx_(true),
-      num_retries_on_5xx_(0),
-      max_retries_on_5xx_(0),
-      num_retries_on_network_changes_(0),
-      max_retries_on_network_changes_(0),
-      current_upload_bytes_(-1),
-      current_response_bytes_(0),
-      total_response_bytes_(-1),
       traffic_annotation_(traffic_annotation) {
   CHECK(original_url_.is_valid());
 }
diff --git a/net/url_request/url_fetcher_core.h b/net/url_request/url_fetcher_core.h
index 656537e..3d37e01 100644
--- a/net/url_request/url_fetcher_core.h
+++ b/net/url_request/url_fetcher_core.h
@@ -254,10 +254,11 @@
   // Task runner for upload file access.
   scoped_refptr<base::TaskRunner> upload_file_task_runner_;
   std::unique_ptr<URLRequest> request_;  // The actual request this wraps
-  int load_flags_;                   // Flags for the load operation
+  int load_flags_ = LOAD_NORMAL;         // Flags for the load operation
   // Whether credentials are sent along with the request.
   absl::optional<bool> allow_credentials_;
-  int response_code_;                // HTTP status code for the request
+  int response_code_ =
+      URLFetcher::RESPONSE_CODE_INVALID;  // HTTP status code for the request
   scoped_refptr<IOBuffer> buffer_;
                                      // Read buffer
   scoped_refptr<URLRequestContextGetter> request_context_getter_;
@@ -269,24 +270,25 @@
   HttpRequestHeaders extra_request_headers_;
   scoped_refptr<HttpResponseHeaders> response_headers_;
   ProxyServer proxy_server_;
-  bool was_cached_;
-  int64_t received_response_content_length_;
-  int64_t total_received_bytes_;
+  bool was_cached_ = false;
+  int64_t received_response_content_length_ = 0;
+  int64_t total_received_bytes_ = 0;
   IPEndPoint remote_endpoint_;
 
-  bool upload_content_set_;          // SetUploadData has been called
+  bool upload_content_set_ = false;  // SetUploadData has been called
   std::string upload_content_;       // HTTP POST payload
   base::FilePath upload_file_path_;  // Path to file containing POST payload
-  uint64_t upload_range_offset_;     // Offset from the beginning of the file
-                                     // to be uploaded.
-  uint64_t upload_range_length_;     // The length of the part of file to be
-                                     // uploaded.
+  uint64_t upload_range_offset_ = 0;  // Offset from the beginning of the file
+                                      // to be uploaded.
+  uint64_t upload_range_length_ = 0;  // The length of the part of file to be
+                                      // uploaded.
   URLFetcher::CreateUploadStreamCallback
       upload_stream_factory_;        // Callback to create HTTP POST payload.
   std::string upload_content_type_;  // MIME type of POST payload
   std::string referrer_;             // HTTP Referer header value and policy
-  ReferrerPolicy referrer_policy_;
-  bool is_chunked_upload_;           // True if using chunked transfer encoding
+  ReferrerPolicy referrer_policy_ =
+      ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+  bool is_chunked_upload_ = false;  // True if using chunked transfer encoding
 
   // Used to write to |chunked_stream|, even after ownership has been passed to
   // the URLRequest. Continues to be valid even after the request deletes its
@@ -316,7 +318,7 @@
   scoped_refptr<URLRequestThrottlerEntryInterface> url_throttler_entry_;
 
   // True if the URLFetcher has been cancelled.
-  bool was_cancelled_;
+  bool was_cancelled_ = false;
 
   // Writer object to write response to the destination like file and string.
   std::unique_ptr<URLFetcherResponseWriter> response_writer_;
@@ -324,42 +326,42 @@
   // By default any server-initiated redirects are automatically followed. If
   // this flag is set to true, however, a redirect will halt the fetch and call
   // back to to the delegate immediately.
-  bool stop_on_redirect_;
+  bool stop_on_redirect_ = false;
   // True when we're actually stopped due to a redirect halted by the above. We
   // use this to ensure that |url_| is set to the redirect destination rather
   // than the originally-fetched URL.
-  bool stopped_on_redirect_;
+  bool stopped_on_redirect_ = false;
 
   // If |automatically_retry_on_5xx_| is false, 5xx responses will be
   // propagated to the observer, if it is true URLFetcher will automatically
   // re-execute the request, after the back-off delay has expired.
   // true by default.
-  bool automatically_retry_on_5xx_;
+  bool automatically_retry_on_5xx_ = true;
   // |num_retries_on_5xx_| indicates how many times we've failed to successfully
   // fetch this URL due to 5xx responses. Once this value exceeds the maximum
   // number of retries specified by the owner URLFetcher instance,
   // we'll give up.
-  int num_retries_on_5xx_;
+  int num_retries_on_5xx_ = 0;
   // Maximum retries allowed when 5xx responses are received.
-  int max_retries_on_5xx_;
+  int max_retries_on_5xx_ = 0;
   // Back-off time delay. 0 by default.
   base::TimeDelta backoff_delay_;
 
   // The number of retries that have been attempted due to ERR_NETWORK_CHANGED.
-  int num_retries_on_network_changes_;
+  int num_retries_on_network_changes_ = 0;
   // Maximum retries allowed when the request fails with ERR_NETWORK_CHANGED.
   // 0 by default.
-  int max_retries_on_network_changes_;
+  int max_retries_on_network_changes_ = 0;
 
   // Timer to poll the progress of uploading for POST and PUT requests.
   // When crbug.com/119629 is fixed, scoped_ptr is not necessary here.
   std::unique_ptr<base::RepeatingTimer> upload_progress_checker_timer_;
   // Number of bytes sent so far.
-  int64_t current_upload_bytes_;
+  int64_t current_upload_bytes_ = -1;
   // Number of bytes received so far.
-  int64_t current_response_bytes_;
+  int64_t current_response_bytes_ = 0;
   // Total expected bytes to receive (-1 if it cannot be determined).
-  int64_t total_response_bytes_;
+  int64_t total_response_bytes_ = -1;
 
   const net::NetworkTrafficAnnotationTag traffic_annotation_;
 
diff --git a/net/url_request/url_fetcher_impl_unittest.cc b/net/url_request/url_fetcher_impl_unittest.cc
index e9c1cba..dad7794 100644
--- a/net/url_request/url_fetcher_impl_unittest.cc
+++ b/net/url_request/url_fetcher_impl_unittest.cc
@@ -66,7 +66,7 @@
 // Can only be used once.
 class WaitingURLFetcherDelegate : public URLFetcherDelegate {
  public:
-  WaitingURLFetcherDelegate() : did_complete_(false) {}
+  WaitingURLFetcherDelegate() = default;
 
   WaitingURLFetcherDelegate(const WaitingURLFetcherDelegate&) = delete;
   WaitingURLFetcherDelegate& operator=(const WaitingURLFetcherDelegate&) =
@@ -154,7 +154,7 @@
   }
 
  private:
-  bool did_complete_;
+  bool did_complete_ = false;
 
   std::unique_ptr<URLFetcherImpl> fetcher_;
   const scoped_refptr<base::SequencedTaskRunner> task_runner_ =
@@ -335,7 +335,7 @@
 
 class URLFetcherTest : public TestWithTaskEnvironment {
  public:
-  URLFetcherTest() : num_upload_streams_created_(0) {}
+  URLFetcherTest() = default;
 
   static int GetNumFetcherCores() {
     return URLFetcherImpl::GetNumFetcherCores();
@@ -470,7 +470,7 @@
   std::unique_ptr<EmbeddedTestServer> test_server_;
   GURL hanging_url_;
 
-  size_t num_upload_streams_created_;
+  size_t num_upload_streams_created_ = 0;
 };
 
 namespace {
@@ -939,8 +939,7 @@
 // been uploaded.
 class CheckUploadProgressDelegate : public WaitingURLFetcherDelegate {
  public:
-  CheckUploadProgressDelegate()
-      : chunk_(1 << 16, 'a'), num_chunks_appended_(0), last_seen_progress_(0) {}
+  CheckUploadProgressDelegate() : chunk_(1 << 16, 'a') {}
 
   CheckUploadProgressDelegate(const CheckUploadProgressDelegate&) = delete;
   CheckUploadProgressDelegate& operator=(const CheckUploadProgressDelegate&) =
@@ -978,8 +977,8 @@
 
   const std::string chunk_;
 
-  int64_t num_chunks_appended_;
-  int64_t last_seen_progress_;
+  int64_t num_chunks_appended_ = 0;
+  int64_t last_seen_progress_ = 0;
 };
 
 TEST_F(URLFetcherTest, UploadProgress) {
@@ -1009,8 +1008,8 @@
 // that file size is correctly reported.
 class CheckDownloadProgressDelegate : public WaitingURLFetcherDelegate {
  public:
-  CheckDownloadProgressDelegate(int64_t file_size)
-      : file_size_(file_size), last_seen_progress_(0) {}
+  explicit CheckDownloadProgressDelegate(int64_t file_size)
+      : file_size_(file_size) {}
 
   CheckDownloadProgressDelegate(const CheckDownloadProgressDelegate&) = delete;
   CheckDownloadProgressDelegate& operator=(
@@ -1033,7 +1032,7 @@
 
  private:
   int64_t file_size_;
-  int64_t last_seen_progress_;
+  int64_t last_seen_progress_ = 0;
 };
 
 TEST_F(URLFetcherTest, DownloadProgress) {
@@ -1422,8 +1421,7 @@
   // request. Can't reuse the old one because fetchers release it on completion.
   ReuseFetcherDelegate(
       scoped_refptr<URLRequestContextGetter> second_request_context_getter)
-      : first_request_complete_(false),
-        second_request_context_getter_(second_request_context_getter) {}
+      : second_request_context_getter_(second_request_context_getter) {}
 
   ReuseFetcherDelegate(const ReuseFetcherDelegate&) = delete;
   ReuseFetcherDelegate& operator=(const ReuseFetcherDelegate&) = delete;
@@ -1450,7 +1448,7 @@
   }
 
  private:
-  bool first_request_complete_;
+  bool first_request_complete_ = false;
   scoped_refptr<URLRequestContextGetter> second_request_context_getter_;
 };
 
diff --git a/net/url_request/url_fetcher_response_writer.cc b/net/url_request/url_fetcher_response_writer.cc
index caf260e0..b3064d9 100644
--- a/net/url_request/url_fetcher_response_writer.cc
+++ b/net/url_request/url_fetcher_response_writer.cc
@@ -55,9 +55,7 @@
 URLFetcherFileWriter::URLFetcherFileWriter(
     scoped_refptr<base::SequencedTaskRunner> file_task_runner,
     const base::FilePath& file_path)
-    : file_task_runner_(file_task_runner),
-      file_path_(file_path),
-      owns_file_(false) {
+    : file_task_runner_(file_task_runner), file_path_(file_path) {
   DCHECK(file_task_runner_.get());
 }
 
diff --git a/net/url_request/url_fetcher_response_writer.h b/net/url_request/url_fetcher_response_writer.h
index 533ad20..474087c 100644
--- a/net/url_request/url_fetcher_response_writer.h
+++ b/net/url_request/url_fetcher_response_writer.h
@@ -140,7 +140,7 @@
   base::FilePath file_path_;
 
   // True when this instance is responsible to delete the file at |file_path_|.
-  bool owns_file_;
+  bool owns_file_ = false;
 
   std::unique_ptr<FileStream> file_stream_;
 
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index fcea2dd..59c2435a 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -577,35 +577,13 @@
     : context_(context),
       net_log_(CreateNetLogWithSource(context->net_log(), net_log_source)),
       url_chain_(1, url),
-      force_ignore_site_for_cookies_(false),
-      force_ignore_top_frame_party_for_cookies_(false),
-      force_main_frame_for_same_site_cookies_(false),
       method_("GET"),
-      referrer_policy_(
-          ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE),
-      first_party_url_policy_(
-          RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL),
-      load_flags_(LOAD_NORMAL),
-      allow_credentials_(true),
-      secure_dns_policy_(SecureDnsPolicy::kAllow),
-#if BUILDFLAG(ENABLE_REPORTING)
-      reporting_upload_depth_(0),
-#endif
       delegate_(delegate),
       is_for_websockets_(is_for_websockets),
-      status_(OK),
-      is_pending_(false),
-      is_redirecting_(false),
       redirect_limit_(kMaxRedirects),
       priority_(priority),
-      delegate_event_type_(NetLogEventType::FAILED),
-      calling_delegate_(false),
-      use_blocked_by_as_load_param_(false),
-      has_notified_completion_(false),
-      received_response_content_length_(0),
       creation_time_(base::TimeTicks::Now()),
-      traffic_annotation_(traffic_annotation),
-      upgrade_if_insecure_(false) {
+      traffic_annotation_(traffic_annotation) {
   // Sanity check out environment.
   DCHECK(base::ThreadTaskRunnerHandle::IsSet());
 
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 3b18dd178..10840b0 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -22,6 +22,7 @@
 #include "net/base/idempotency.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/isolation_info.h"
+#include "net/base/load_flags.h"
 #include "net/base/load_states.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/net_error_details.h"
@@ -938,29 +939,31 @@
 
   IsolationInfo isolation_info_;
 
-  bool force_ignore_site_for_cookies_;
-  bool force_ignore_top_frame_party_for_cookies_;
-  bool force_main_frame_for_same_site_cookies_;
+  bool force_ignore_site_for_cookies_ = false;
+  bool force_ignore_top_frame_party_for_cookies_ = false;
+  bool force_main_frame_for_same_site_cookies_ = false;
   absl::optional<url::Origin> initiator_;
   GURL delegate_redirect_url_;
   std::string method_;  // "GET", "POST", etc. Should be all uppercase.
   std::string referrer_;
-  ReferrerPolicy referrer_policy_;
-  RedirectInfo::FirstPartyURLPolicy first_party_url_policy_;
+  ReferrerPolicy referrer_policy_ =
+      ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+  RedirectInfo::FirstPartyURLPolicy first_party_url_policy_ =
+      RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
   HttpRequestHeaders extra_request_headers_;
   // Flags indicating the request type for the load. Expected values are LOAD_*
   // enums above.
-  int load_flags_;
+  int load_flags_ = LOAD_NORMAL;
   // Whether the request is allowed to send credentials in general. Set by
   // caller.
-  bool allow_credentials_;
-  SecureDnsPolicy secure_dns_policy_;
+  bool allow_credentials_ = true;
+  SecureDnsPolicy secure_dns_policy_ = SecureDnsPolicy::kAllow;
 
   CookieAccessResultList maybe_sent_cookies_;
   CookieAndLineAccessResultList maybe_stored_cookies_;
 
 #if BUILDFLAG(ENABLE_REPORTING)
-  int reporting_upload_depth_;
+  int reporting_upload_depth_ = 0;
 #endif
 
   // Never access methods of the |delegate_| directly. Always use the
@@ -980,7 +983,7 @@
   // but once an error is encountered or the request is canceled, it will take
   // the appropriate error code and never change again. If multiple failures
   // have been encountered, this will be the first error encountered.
-  int status_;
+  int status_ = OK;
 
   // The HTTP response info, lazily initialized.
   HttpResponseInfo response_info_;
@@ -988,12 +991,12 @@
   // Tells us whether the job is outstanding. This is true from the time
   // Start() is called to the time we dispatch RequestComplete and indicates
   // whether the job is active.
-  bool is_pending_;
+  bool is_pending_ = false;
 
   // Indicates if the request is in the process of redirecting to a new
   // location.  It is true from the time the headers complete until a
   // new request begins.
-  bool is_redirecting_;
+  bool is_redirecting_ = false;
 
   // Number of times we're willing to redirect.  Used to guard against
   // infinite redirects.
@@ -1010,23 +1013,23 @@
 
   // If |calling_delegate_| is true, the event type of the delegate being
   // called.
-  NetLogEventType delegate_event_type_;
+  NetLogEventType delegate_event_type_ = NetLogEventType::FAILED;
 
   // True if this request is currently calling a delegate, or is blocked waiting
   // for the URL request or network delegate to resume it.
-  bool calling_delegate_;
+  bool calling_delegate_ = false;
 
   // An optional parameter that provides additional information about what
   // |this| is currently being blocked by.
   std::string blocked_by_;
-  bool use_blocked_by_as_load_param_;
+  bool use_blocked_by_as_load_param_ = false;
 
   // Safe-guard to ensure that we do not send multiple "I am completed"
   // messages to network delegate.
   // TODO(battre): Remove this. http://crbug.com/89049
-  bool has_notified_completion_;
+  bool has_notified_completion_ = false;
 
-  int64_t received_response_content_length_;
+  int64_t received_response_content_length_ = 0;
 
   base::TimeTicks creation_time_;
 
@@ -1063,7 +1066,7 @@
   // entry will be marked as unusable and will not be re-used.
   std::string expected_response_checksum_;
 
-  bool upgrade_if_insecure_;
+  bool upgrade_if_insecure_ = false;
 
   bool send_client_certs_ = true;
 
diff --git a/net/url_request/url_request_context.cc b/net/url_request/url_request_context.cc
index 49a4284..0c0847c 100644
--- a/net/url_request/url_request_context.cc
+++ b/net/url_request/url_request_context.cc
@@ -55,9 +55,6 @@
       network_error_logging_service_(nullptr),
 #endif  // BUILDFLAG(ENABLE_REPORTING)
       url_requests_(std::make_unique<std::set<const URLRequest*>>()),
-      enable_brotli_(false),
-      check_cleartext_permitted_(false),
-      require_network_isolation_key_(false),
       bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) {
 }
 
diff --git a/net/url_request/url_request_context.h b/net/url_request/url_request_context.h
index 27df35f..9da6d7e 100644
--- a/net/url_request/url_request_context.h
+++ b/net/url_request/url_request_context.h
@@ -352,14 +352,14 @@
   std::unique_ptr<std::set<const URLRequest*>> url_requests_;
 
   // Enables Brotli Content-Encoding support.
-  bool enable_brotli_;
+  bool enable_brotli_ = false;
   // Enables checking system policy before allowing a cleartext http or ws
   // request. Only used on Android.
-  bool check_cleartext_permitted_;
+  bool check_cleartext_permitted_ = false;
 
   // Triggers a DCHECK if a NetworkIsolationKey/IsolationInfo is not provided to
   // a request when true.
-  bool require_network_isolation_key_;
+  bool require_network_isolation_key_ = false;
 
   NetworkChangeNotifier::NetworkHandle bound_network_;
 
diff --git a/net/url_request/url_request_context_builder.cc b/net/url_request/url_request_context_builder.cc
index f011342..d8a383a6 100644
--- a/net/url_request/url_request_context_builder.cc
+++ b/net/url_request/url_request_context_builder.cc
@@ -125,8 +125,7 @@
 
 }  // namespace
 
-URLRequestContextBuilder::HttpCacheParams::HttpCacheParams()
-    : type(IN_MEMORY), max_size(0), reset_cache(false) {}
+URLRequestContextBuilder::HttpCacheParams::HttpCacheParams() = default;
 URLRequestContextBuilder::HttpCacheParams::~HttpCacheParams() = default;
 
 URLRequestContextBuilder::URLRequestContextBuilder() = default;
diff --git a/net/url_request/url_request_context_builder.h b/net/url_request/url_request_context_builder.h
index 0a8de9e9..572a764 100644
--- a/net/url_request/url_request_context_builder.h
+++ b/net/url_request/url_request_context_builder.h
@@ -110,14 +110,14 @@
     ~HttpCacheParams();
 
     // The type of HTTP cache. Default is IN_MEMORY.
-    Type type;
+    Type type = IN_MEMORY;
 
     // The max size of the cache in bytes. Default is algorithmically determined
     // based off available disk space.
-    int max_size;
+    int max_size = 0;
 
     // Whether or not we need to reset the cache due to an experiment change.
-    bool reset_cache;
+    bool reset_cache = false;
 
     // The cache path (when type is DISK).
     base::FilePath path;
diff --git a/net/url_request/url_request_filter.cc b/net/url_request/url_request_filter.cc
index 7ac17525..9a19dde 100644
--- a/net/url_request/url_request_filter.cc
+++ b/net/url_request/url_request_filter.cc
@@ -140,7 +140,7 @@
   return job;
 }
 
-URLRequestFilter::URLRequestFilter() : hit_count_(0) {
+URLRequestFilter::URLRequestFilter() {
   DCHECK(OnMessageLoopForInterceptorAddition());
   URLRequestJobFactory::SetInterceptorForTesting(this);
 }
diff --git a/net/url_request/url_request_filter.h b/net/url_request/url_request_filter.h
index 44943f3..134f029 100644
--- a/net/url_request/url_request_filter.h
+++ b/net/url_request/url_request_filter.h
@@ -88,7 +88,7 @@
   // Maps URLs to interceptors.
   URLInterceptorMap url_interceptor_map_;
 
-  mutable int hit_count_;
+  mutable int hit_count_ = 0;
 
   // Singleton instance.
   static URLRequestFilter* shared_instance_;
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 619573f..d170e20 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -229,18 +229,9 @@
     URLRequest* request,
     const HttpUserAgentSettings* http_user_agent_settings)
     : URLRequestJob(request),
-      num_cookie_lines_left_(0),
-      priority_(DEFAULT_PRIORITY),
       response_info_(nullptr),
-      proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
-      server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
-      read_in_progress_(false),
       throttling_entry_(nullptr),
-      done_(false),
-      awaiting_callback_(false),
-      http_user_agent_settings_(http_user_agent_settings),
-      total_received_bytes_from_previous_transactions_(0),
-      total_sent_bytes_from_previous_transactions_(0) {
+      http_user_agent_settings_(http_user_agent_settings) {
   URLRequestThrottlerManager* manager = request->context()->throttler_manager();
   if (manager)
     throttling_entry_ = manager->RegisterRequestUrl(request->url());
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index f2fcb73..7bc5cf5 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -201,7 +201,7 @@
                          absl::optional<CanonicalCookie> cookie,
                          std::string cookie_string,
                          CookieAccessResult access_result);
-  int num_cookie_lines_left_;
+  int num_cookie_lines_left_ = 0;
   CookieAndLineAccessResultList set_cookie_access_result_list_;
 
   // Some servers send the body compressed, but specify the content length as
@@ -229,7 +229,7 @@
   // set.
   bool IsPartitionedCookiesEnabled() const;
 
-  RequestPriority priority_;
+  RequestPriority priority_ = DEFAULT_PRIORITY;
 
   HttpRequestInfo request_info_;
   raw_ptr<const HttpResponseInfo> response_info_;
@@ -240,11 +240,11 @@
   std::unique_ptr<HttpResponseInfo> override_response_info_;
 
   // Auth states for proxy and origin server.
-  AuthState proxy_auth_state_;
-  AuthState server_auth_state_;
+  AuthState proxy_auth_state_ = AUTH_STATE_DONT_NEED_AUTH;
+  AuthState server_auth_state_ = AUTH_STATE_DONT_NEED_AUTH;
   AuthCredentials auth_credentials_;
 
-  bool read_in_progress_;
+  bool read_in_progress_ = false;
 
   std::unique_ptr<HttpTransaction> transaction_;
 
@@ -255,7 +255,7 @@
   base::Time request_creation_time_;
 
   // True when we are done doing work.
-  bool done_;
+  bool done_ = false;
 
   // The start time for the job, ignoring re-starts.
   base::TimeTicks start_time_;
@@ -283,16 +283,16 @@
   // True if we are waiting a callback and
   // NetworkDelegate::NotifyURLRequestDestroyed has not been called, yet,
   // to inform the NetworkDelegate that it may not call back.
-  bool awaiting_callback_;
+  bool awaiting_callback_ = false;
 
   raw_ptr<const HttpUserAgentSettings> http_user_agent_settings_;
 
   // Keeps track of total received bytes over the network from transactions used
   // by this job that have already been destroyed.
-  int64_t total_received_bytes_from_previous_transactions_;
+  int64_t total_received_bytes_from_previous_transactions_ = 0;
   // Keeps track of total sent bytes over the network from transactions used by
   // this job that have already been destroyed.
-  int64_t total_sent_bytes_from_previous_transactions_;
+  int64_t total_sent_bytes_from_previous_transactions_ = 0;
 
   RequestHeadersCallback request_headers_callback_;
   ResponseHeadersCallback early_response_headers_callback_;
diff --git a/net/url_request/url_request_http_job_unittest.cc b/net/url_request/url_request_http_job_unittest.cc
index a53909f..6cfcbd5 100644
--- a/net/url_request/url_request_http_job_unittest.cc
+++ b/net/url_request/url_request_http_job_unittest.cc
@@ -103,8 +103,7 @@
  public:
   explicit TestURLRequestHttpJob(URLRequest* request)
       : URLRequestHttpJob(request,
-                          request->context()->http_user_agent_settings()),
-        use_null_source_stream_(false) {}
+                          request->context()->http_user_agent_settings()) {}
 
   TestURLRequestHttpJob(const TestURLRequestHttpJob&) = delete;
   TestURLRequestHttpJob& operator=(const TestURLRequestHttpJob&) = delete;
@@ -128,7 +127,7 @@
   using URLRequestHttpJob::priority;
 
  private:
-  bool use_null_source_stream_;
+  bool use_null_source_stream_ = false;
 };
 
 class URLRequestHttpJobSetUpSourceTest : public TestWithTaskEnvironment {
diff --git a/net/url_request/url_request_job.cc b/net/url_request/url_request_job.cc
index 9b7a9832..9262d5b 100644
--- a/net/url_request/url_request_job.cc
+++ b/net/url_request/url_request_job.cc
@@ -84,13 +84,7 @@
   const raw_ptr<URLRequestJob> job_;
 };
 
-URLRequestJob::URLRequestJob(URLRequest* request)
-    : request_(request),
-      done_(false),
-      prefilter_bytes_read_(0),
-      postfilter_bytes_read_(0),
-      has_handled_response_(false),
-      expected_content_size_(-1) {}
+URLRequestJob::URLRequestJob(URLRequest* request) : request_(request) {}
 
 URLRequestJob::~URLRequestJob() {
 }
diff --git a/net/url_request/url_request_job.h b/net/url_request/url_request_job.h
index 39496e38..0f55a00b 100644
--- a/net/url_request/url_request_job.h
+++ b/net/url_request/url_request_job.h
@@ -408,13 +408,13 @@
   // Indicates that the job is done producing data, either it has completed
   // all the data or an error has been encountered. Set exclusively by
   // NotifyDone so that it is kept in sync with the request.
-  bool done_;
+  bool done_ = false;
 
   // Number of raw network bytes read from job subclass.
-  int64_t prefilter_bytes_read_;
+  int64_t prefilter_bytes_read_ = 0;
 
   // Number of bytes after applying |source_stream_| filters.
-  int64_t postfilter_bytes_read_;
+  int64_t postfilter_bytes_read_ = 0;
 
   // The first SourceStream of the SourceStream chain used.
   std::unique_ptr<SourceStream> source_stream_;
@@ -429,10 +429,10 @@
 
   // Used by HandleResponseIfNecessary to track whether we've sent the
   // OnResponseStarted callback and potentially redirect callbacks as well.
-  bool has_handled_response_;
+  bool has_handled_response_ = false;
 
   // Expected content size
-  int64_t expected_content_size_;
+  int64_t expected_content_size_ = -1;
 
   // Set when a redirect is deferred. Redirects are deferred after validity
   // checks are performed, so this field must not be modified.
diff --git a/net/url_request/url_request_test_util.cc b/net/url_request/url_request_test_util.cc
index 194b0871..e186610 100644
--- a/net/url_request/url_request_test_util.cc
+++ b/net/url_request/url_request_test_util.cc
@@ -304,24 +304,7 @@
     std::move(on_complete_).Run();
 }
 
-TestNetworkDelegate::TestNetworkDelegate()
-    : last_error_(0),
-      error_count_(0),
-      created_requests_(0),
-      destroyed_requests_(0),
-      completed_requests_(0),
-      canceled_requests_(0),
-      cookie_options_bit_mask_(0),
-      blocked_annotate_cookies_count_(0),
-      blocked_set_cookie_count_(0),
-      set_cookie_count_(0),
-      before_start_transaction_count_(0),
-      headers_received_count_(0),
-      has_load_timing_info_before_redirect_(false),
-      cancel_request_with_policy_violating_referrer_(false),
-      before_start_transaction_fails_(false),
-      add_header_to_first_response_(false),
-      next_request_id_(0) {}
+TestNetworkDelegate::TestNetworkDelegate() = default;
 
 TestNetworkDelegate::~TestNetworkDelegate() {
   for (auto i = next_states_.begin(); i != next_states_.end(); ++i) {
diff --git a/net/url_request/url_request_test_util.h b/net/url_request/url_request_test_util.h
index 33794203..05e5399f 100644
--- a/net/url_request/url_request_test_util.h
+++ b/net/url_request/url_request_test_util.h
@@ -338,18 +338,18 @@
   // OnHeadersReceived() stage.
   absl::optional<GURL> preserve_fragment_on_redirect_url_;
 
-  int last_error_;
-  int error_count_;
-  int created_requests_;
-  int destroyed_requests_;
-  int completed_requests_;
-  int canceled_requests_;
-  int cookie_options_bit_mask_;
-  int blocked_annotate_cookies_count_;
-  int blocked_set_cookie_count_;
-  int set_cookie_count_;
-  int before_start_transaction_count_;
-  int headers_received_count_;
+  int last_error_ = 0;
+  int error_count_ = 0;
+  int created_requests_ = 0;
+  int destroyed_requests_ = 0;
+  int completed_requests_ = 0;
+  int canceled_requests_ = 0;
+  int cookie_options_bit_mask_ = 0;
+  int blocked_annotate_cookies_count_ = 0;
+  int blocked_set_cookie_count_ = 0;
+  int set_cookie_count_ = 0;
+  int before_start_transaction_count_ = 0;
+  int headers_received_count_ = 0;
 
   // NetworkDelegate callbacks happen in a particular order (e.g.
   // OnBeforeURLRequest is always called before OnBeforeStartTransaction).
@@ -362,12 +362,13 @@
   std::map<int, std::string> event_order_;
 
   LoadTimingInfo load_timing_info_before_redirect_;
-  bool has_load_timing_info_before_redirect_;
+  bool has_load_timing_info_before_redirect_ = false;
 
-  bool cancel_request_with_policy_violating_referrer_;  // false by default
-  bool before_start_transaction_fails_;
-  bool add_header_to_first_response_;
-  int next_request_id_;
+  bool cancel_request_with_policy_violating_referrer_ =
+      false;  // false by default
+  bool before_start_transaction_fails_ = false;
+  bool add_header_to_first_response_ = false;
+  int next_request_id_ = 0;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/net/url_request/url_request_throttler_manager.cc b/net/url_request/url_request_throttler_manager.cc
index 1aff5e8..9fb5ca1 100644
--- a/net/url_request/url_request_throttler_manager.cc
+++ b/net/url_request/url_request_throttler_manager.cc
@@ -17,9 +17,7 @@
 const unsigned int URLRequestThrottlerManager::kRequestsBetweenCollecting = 200;
 
 URLRequestThrottlerManager::URLRequestThrottlerManager()
-    : requests_since_last_gc_(0),
-      logged_for_localhost_disabled_(false),
-      registered_from_thread_(base::kInvalidThreadId) {
+    : registered_from_thread_(base::kInvalidThreadId) {
   url_id_replacements_.ClearPassword();
   url_id_replacements_.ClearUsername();
   url_id_replacements_.ClearQuery();
diff --git a/net/url_request/url_request_throttler_manager.h b/net/url_request/url_request_throttler_manager.h
index 3f533f5..5b6a98a6 100644
--- a/net/url_request/url_request_throttler_manager.h
+++ b/net/url_request/url_request_throttler_manager.h
@@ -120,7 +120,7 @@
 
   // This keeps track of how many requests have been made. Used with
   // GarbageCollectEntries.
-  unsigned int requests_since_last_gc_;
+  unsigned int requests_since_last_gc_ = 0;
 
   // Valid after construction.
   GURL::Replacements url_id_replacements_;
@@ -135,7 +135,7 @@
 
   // Initially false, switches to true once we have logged because of back-off
   // being disabled for localhost.
-  bool logged_for_localhost_disabled_;
+  bool logged_for_localhost_disabled_ = false;
 
   // NetLog to use, if configured.
   NetLogWithSource net_log_;
diff --git a/net/url_request/url_request_throttler_simulation_unittest.cc b/net/url_request/url_request_throttler_simulation_unittest.cc
index e55ed330..f7c2bac 100644
--- a/net/url_request/url_request_throttler_simulation_unittest.cc
+++ b/net/url_request/url_request_throttler_simulation_unittest.cc
@@ -122,10 +122,6 @@
   Server(int max_queries_per_tick, double request_drop_ratio)
       : max_queries_per_tick_(max_queries_per_tick),
         request_drop_ratio_(request_drop_ratio),
-        num_overloaded_ticks_remaining_(0),
-        num_current_tick_queries_(0),
-        num_overloaded_ticks_(0),
-        max_experienced_queries_per_tick_(0),
         context_(CreateTestURLRequestContextBuilder()->Build()),
         mock_request_(context_->CreateRequest(GURL(),
                                               DEFAULT_PRIORITY,
@@ -293,10 +289,10 @@
   TimeTicks end_downtime_;
   const int max_queries_per_tick_;
   const double request_drop_ratio_;  // Ratio of requests to 503 when failing.
-  int num_overloaded_ticks_remaining_;
-  int num_current_tick_queries_;
-  int num_overloaded_ticks_;
-  int max_experienced_queries_per_tick_;
+  int num_overloaded_ticks_remaining_ = 0;
+  int num_current_tick_queries_ = 0;
+  int num_overloaded_ticks_ = 0;
+  int max_experienced_queries_per_tick_ = 0;
   std::vector<int> requests_per_tick_;
 
   std::unique_ptr<URLRequestContext> context_;
@@ -334,9 +330,7 @@
 // regular clients).
 class RequesterResults {
  public:
-  RequesterResults()
-      : num_attempts_(0), num_successful_(0), num_failed_(0), num_blocked_(0) {
-  }
+  RequesterResults() = default;
 
   void AddSuccess() {
     ++num_attempts_;
@@ -387,10 +381,10 @@
   }
 
  private:
-  int num_attempts_;
-  int num_successful_;
-  int num_failed_;
-  int num_blocked_;
+  int num_attempts_ = 0;
+  int num_successful_ = 0;
+  int num_failed_ = 0;
+  int num_blocked_ = 0;
 };
 
 // Represents an Requester in a simulated DDoS situation, that periodically
@@ -403,7 +397,6 @@
             RequesterResults* results)
       : throttler_entry_(throttler_entry),
         time_between_requests_(time_between_requests),
-        last_attempt_was_failure_(false),
         server_(server),
         results_(results) {
     DCHECK(server_);
@@ -477,7 +470,7 @@
   base::TimeDelta request_jitter_;
   TimeTicks time_of_last_attempt_;
   TimeTicks time_of_last_success_;
-  bool last_attempt_was_failure_;
+  bool last_attempt_was_failure_ = false;
   base::TimeDelta last_downtime_duration_;
   const raw_ptr<Server> server_;
   const raw_ptr<RequesterResults> results_;  // May be NULL.
diff --git a/net/url_request/url_request_throttler_unittest.cc b/net/url_request/url_request_throttler_unittest.cc
index 2f748210..98c2aea 100644
--- a/net/url_request/url_request_throttler_unittest.cc
+++ b/net/url_request/url_request_throttler_unittest.cc
@@ -101,7 +101,7 @@
 
 class MockURLRequestThrottlerManager : public URLRequestThrottlerManager {
  public:
-  MockURLRequestThrottlerManager() : create_entry_index_(0) {}
+  MockURLRequestThrottlerManager() = default;
 
   // Method to process the URL using URLRequestThrottlerManager protected
   // method.
@@ -129,7 +129,7 @@
   }
 
  private:
-  int create_entry_index_;
+  int create_entry_index_ = 0;
 };
 
 struct TimeAndBool {
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 62a007b1..66b18c5 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -445,15 +445,15 @@
 
   // Values returned on blocking stages when mode is SYNCHRONOUS or
   // AUTO_CALLBACK. For USER_CALLBACK these are set automatically to IO_PENDING.
-  int retval_;
+  int retval_ = OK;
 
   GURL redirect_url_;  // Used if non-empty during OnBeforeURLRequest.
-  int block_on_;       // Bit mask: in which stages to block.
+  int block_on_ = 0;   // Bit mask: in which stages to block.
 
   // Internal variables, not set by not the user:
   // Last blocked stage waiting for user callback (unused if |block_mode_| !=
   // USER_CALLBACK).
-  Stage stage_blocked_for_callback_;
+  Stage stage_blocked_for_callback_ = NOT_BLOCKED;
 
   // Callback objects stored during blocking stages.
   CompletionOnceCallback callback_;
@@ -465,10 +465,7 @@
 };
 
 BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode)
-    : block_mode_(block_mode),
-      retval_(OK),
-      block_on_(0),
-      stage_blocked_for_callback_(NOT_BLOCKED) {}
+    : block_mode_(block_mode) {}
 
 void BlockingNetworkDelegate::RunUntilBlocked() {
   base::RunLoop run_loop;
@@ -6399,7 +6396,7 @@
 // called.
 class MockExpectCTReporter : public TransportSecurityState::ExpectCTReporter {
  public:
-  MockExpectCTReporter() : num_failures_(0) {}
+  MockExpectCTReporter() = default;
   ~MockExpectCTReporter() override = default;
 
   void OnExpectCTFailed(
@@ -6417,15 +6414,14 @@
   uint32_t num_failures() { return num_failures_; }
 
  private:
-  uint32_t num_failures_;
+  uint32_t num_failures_ = 0;
 };
 
 // A CTPolicyEnforcer that returns a default CTPolicyCompliance value
 // for every certificate.
 class MockCTPolicyEnforcer : public CTPolicyEnforcer {
  public:
-  MockCTPolicyEnforcer()
-      : default_result_(ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS) {}
+  MockCTPolicyEnforcer() = default;
   ~MockCTPolicyEnforcer() override = default;
 
   ct::CTPolicyCompliance CheckCompliance(
@@ -6440,7 +6436,8 @@
   }
 
  private:
-  ct::CTPolicyCompliance default_result_;
+  ct::CTPolicyCompliance default_result_ =
+      ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS;
 };
 
 // Tests that Expect CT headers for the preload list are processed correctly.
@@ -9977,9 +9974,7 @@
 
 class SSLClientAuthTestDelegate : public TestDelegate {
  public:
-  SSLClientAuthTestDelegate() : on_certificate_requested_count_(0) {
-    set_on_complete(base::DoNothing());
-  }
+  SSLClientAuthTestDelegate() { set_on_complete(base::DoNothing()); }
   void OnCertificateRequested(URLRequest* request,
                               SSLCertRequestInfo* cert_request_info) override {
     on_certificate_requested_count_++;
@@ -9995,7 +9990,7 @@
   }
 
  private:
-  int on_certificate_requested_count_;
+  int on_certificate_requested_count_ = 0;
   base::OnceClosure on_certificate_requested_;
 };
 
diff --git a/net/websockets/websocket_basic_handshake_stream.cc b/net/websockets/websocket_basic_handshake_stream.cc
index 79f1a63..d66b4b9 100644
--- a/net/websockets/websocket_basic_handshake_stream.cc
+++ b/net/websockets/websocket_basic_handshake_stream.cc
@@ -177,8 +177,7 @@
     std::vector<std::string> requested_extensions,
     WebSocketStreamRequestAPI* request,
     WebSocketEndpointLockManager* websocket_endpoint_lock_manager)
-    : result_(HandshakeResult::INCOMPLETE),
-      state_(std::move(connection), using_proxy),
+    : state_(std::move(connection), using_proxy),
       connect_delegate_(connect_delegate),
       http_response_info_(nullptr),
       requested_sub_protocols_(std::move(requested_sub_protocols)),
diff --git a/net/websockets/websocket_basic_handshake_stream.h b/net/websockets/websocket_basic_handshake_stream.h
index 8496184..8b84684 100644
--- a/net/websockets/websocket_basic_handshake_stream.h
+++ b/net/websockets/websocket_basic_handshake_stream.h
@@ -115,7 +115,7 @@
 
   HttpStreamParser* parser() const { return state_.parser(); }
 
-  HandshakeResult result_;
+  HandshakeResult result_ = HandshakeResult::INCOMPLETE;
 
   // The request URL.
   GURL url_;
diff --git a/net/websockets/websocket_basic_stream_adapters.cc b/net/websockets/websocket_basic_stream_adapters.cc
index 0855172..88144bd2 100644
--- a/net/websockets/websocket_basic_stream_adapters.cc
+++ b/net/websockets/websocket_basic_stream_adapters.cc
@@ -52,12 +52,7 @@
     base::WeakPtr<SpdyStream> stream,
     Delegate* delegate,
     NetLogWithSource net_log)
-    : headers_sent_(false),
-      stream_(stream),
-      stream_error_(ERR_CONNECTION_CLOSED),
-      delegate_(delegate),
-      write_length_(0),
-      net_log_(net_log) {
+    : stream_(stream), delegate_(delegate), net_log_(net_log) {
   stream_->SetDelegate(this);
 }
 
diff --git a/net/websockets/websocket_basic_stream_adapters.h b/net/websockets/websocket_basic_stream_adapters.h
index 0052524..e522abac 100644
--- a/net/websockets/websocket_basic_stream_adapters.h
+++ b/net/websockets/websocket_basic_stream_adapters.h
@@ -115,13 +115,13 @@
 
   // True if SpdyStream::Delegate::OnHeadersSent() has been called.
   // SpdyStream::SendData() must not be called before that.
-  bool headers_sent_;
+  bool headers_sent_ = false;
 
   // The underlying SpdyStream.
   base::WeakPtr<SpdyStream> stream_;
 
   // The error code with which SpdyStream was closed.
-  int stream_error_;
+  int stream_error_ = ERR_CONNECTION_CLOSED;
 
   raw_ptr<Delegate> delegate_;
 
@@ -140,7 +140,7 @@
   // Write length saved to be passed to |write_callback_|.  This is necessary
   // because SpdyStream::Delegate::OnDataSent() does not pass number of bytes
   // written.
-  int write_length_;
+  int write_length_ = 0;
 
   // Write callback saved for asynchronous writes (all writes are asynchronous).
   CompletionOnceCallback write_callback_;
diff --git a/net/websockets/websocket_basic_stream_test.cc b/net/websockets/websocket_basic_stream_test.cc
index 440da1d..1d5ab38 100644
--- a/net/websockets/websocket_basic_stream_test.cc
+++ b/net/websockets/websocket_basic_stream_test.cc
@@ -128,8 +128,7 @@
             nullptr /* net_log */,
             nullptr /* websocket_endpoint_lock_manager */),
         pool_(1, 1, &common_connect_job_params_),
-        generator_(&GenerateNulMaskingKey),
-        expect_all_io_to_complete_(true) {}
+        generator_(&GenerateNulMaskingKey) {}
 
   ~WebSocketBasicStreamSocketTest() override {
     // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
@@ -184,7 +183,7 @@
   std::string extensions_;
   NetLogWithSource net_log_;
   WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
-  bool expect_all_io_to_complete_;
+  bool expect_all_io_to_complete_ = true;
   std::unique_ptr<WebSocketBasicStream> stream_;
 };
 
diff --git a/net/websockets/websocket_channel.cc b/net/websockets/websocket_channel.cc
index 84d37a7..8360beff 100644
--- a/net/websockets/websocket_channel.cc
+++ b/net/websockets/websocket_channel.cc
@@ -150,7 +150,7 @@
 // those frames.
 class WebSocketChannel::SendBuffer {
  public:
-  SendBuffer() : total_bytes_(0) {}
+  SendBuffer() = default;
 
   // Add a WebSocketFrame to the buffer and increase total_bytes_.
   void AddFrame(std::unique_ptr<WebSocketFrame> chunk,
@@ -168,7 +168,7 @@
   // The total size of the payload data in |frames_|. This will be used to
   // measure the throughput of the link.
   // TODO(ricea): Measure the throughput of the link.
-  uint64_t total_bytes_;
+  uint64_t total_bytes_ = 0;
 };
 
 void WebSocketChannel::SendBuffer::AddFrame(
@@ -248,14 +248,7 @@
       closing_handshake_timeout_(
           base::Seconds(kClosingHandshakeTimeoutSeconds)),
       underlying_connection_close_timeout_(
-          base::Seconds(kUnderlyingConnectionCloseTimeoutSeconds)),
-      has_received_close_frame_(false),
-      received_close_code_(0),
-      state_(FRESHLY_CONSTRUCTED),
-      sending_text_message_(false),
-      receiving_text_message_(false),
-      expecting_to_handle_continuation_(false),
-      initial_frame_forwarded_(false) {}
+          base::Seconds(kUnderlyingConnectionCloseTimeoutSeconds)) {}
 
 WebSocketChannel::~WebSocketChannel() {
   // The stream may hold a pointer to read_frames_, and so it needs to be
diff --git a/net/websockets/websocket_channel.h b/net/websockets/websocket_channel.h
index 52c00d9a..c8d9690 100644
--- a/net/websockets/websocket_channel.h
+++ b/net/websockets/websocket_channel.h
@@ -366,28 +366,28 @@
   // Storage for the status code and reason from the time the Close frame
   // arrives until the connection is closed and they are passed to
   // OnDropChannel().
-  bool has_received_close_frame_;
-  uint16_t received_close_code_;
+  bool has_received_close_frame_ = false;
+  uint16_t received_close_code_ = 0;
   std::string received_close_reason_;
 
   // The current state of the channel. Mainly used for sanity checking, but also
   // used to track the close state.
-  State state_;
+  State state_ = FRESHLY_CONSTRUCTED;
 
   // UTF-8 validator for outgoing Text messages.
   base::StreamingUtf8Validator outgoing_utf8_validator_;
-  bool sending_text_message_;
+  bool sending_text_message_ = false;
 
   // UTF-8 validator for incoming Text messages.
   base::StreamingUtf8Validator incoming_utf8_validator_;
-  bool receiving_text_message_;
+  bool receiving_text_message_ = false;
 
   // True if we are in the middle of receiving a message.
-  bool expecting_to_handle_continuation_;
+  bool expecting_to_handle_continuation_ = false;
 
   // True if we have already sent the type (Text or Binary) of the current
   // message to the renderer. This can be false if the message is empty so far.
-  bool initial_frame_forwarded_;
+  bool initial_frame_forwarded_ = false;
 
   // True if we're waiting for OnReadDone() callback.
   bool is_reading_ = false;
diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
index f797576..7ac0456 100644
--- a/net/websockets/websocket_channel_test.cc
+++ b/net/websockets/websocket_channel_test.cc
@@ -468,7 +468,7 @@
 
   // After constructing the object, call PrepareReadFrames() once for each
   // time you wish it to return from the test.
-  ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {}
+  ReadableFakeWebSocketStream() = default;
 
   // Check that all the prepared responses have been consumed.
   ~ReadableFakeWebSocketStream() override {
@@ -555,13 +555,13 @@
   std::vector<std::unique_ptr<Response>> responses_;
 
   // The index into the responses_ array of the next response to be returned.
-  size_t index_;
+  size_t index_ = 0;
 
   // True when an async response from ReadFrames() is pending. This only applies
   // to "real" async responses. Once all the prepared responses have been
   // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
   // not set to true.
-  bool read_frames_pending_;
+  bool read_frames_pending_ = false;
 
   std::vector<scoped_refptr<IOBuffer>> result_frame_data_;
 };
@@ -593,7 +593,7 @@
 // otherwise the ReadFrames() callback will never be called.
 class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
  public:
-  EchoeyFakeWebSocketStream() : read_frames_(nullptr), done_(false) {}
+  EchoeyFakeWebSocketStream() : read_frames_(nullptr) {}
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
                   CompletionOnceCallback callback) override {
@@ -661,7 +661,7 @@
   raw_ptr<std::vector<std::unique_ptr<WebSocketFrame>>> read_frames_;
   std::vector<scoped_refptr<IOBuffer>> buffers_;
   // True if we should close the connection.
-  bool done_;
+  bool done_ = false;
 };
 
 // A FakeWebSocketStream where writes trigger a connection reset.
@@ -673,7 +673,7 @@
 // 2. Calling either callback may delete the stream altogether.
 class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
  public:
-  ResetOnWriteFakeWebSocketStream() : closed_(false) {}
+  ResetOnWriteFakeWebSocketStream() = default;
 
   int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
                   CompletionOnceCallback callback) override {
@@ -707,7 +707,7 @@
   }
 
   CompletionOnceCallback read_callback_;
-  bool closed_;
+  bool closed_ = false;
   // An IO error can result in the socket being deleted, so we use weak pointers
   // to ensure correct behaviour in that case.
   base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_{this};
diff --git a/net/websockets/websocket_deflate_stream.cc b/net/websockets/websocket_deflate_stream.cc
index 229cdd0..709d9a14 100644
--- a/net/websockets/websocket_deflate_stream.cc
+++ b/net/websockets/websocket_deflate_stream.cc
@@ -42,10 +42,6 @@
     : stream_(std::move(stream)),
       deflater_(params.client_context_take_over_mode()),
       inflater_(kChunkSize, kChunkSize),
-      reading_state_(NOT_READING),
-      writing_state_(NOT_WRITING),
-      current_reading_opcode_(WebSocketFrameHeader::kOpCodeText),
-      current_writing_opcode_(WebSocketFrameHeader::kOpCodeText),
       predictor_(std::move(predictor)) {
   DCHECK(stream_);
   DCHECK(params.IsValidAsResponse());
diff --git a/net/websockets/websocket_deflate_stream.h b/net/websockets/websocket_deflate_stream.h
index fecd09569..ad5f0872 100644
--- a/net/websockets/websocket_deflate_stream.h
+++ b/net/websockets/websocket_deflate_stream.h
@@ -98,10 +98,12 @@
   const std::unique_ptr<WebSocketStream> stream_;
   WebSocketDeflater deflater_;
   WebSocketInflater inflater_;
-  ReadingState reading_state_;
-  WritingState writing_state_;
-  WebSocketFrameHeader::OpCode current_reading_opcode_;
-  WebSocketFrameHeader::OpCode current_writing_opcode_;
+  ReadingState reading_state_ = NOT_READING;
+  WritingState writing_state_ = NOT_WRITING;
+  WebSocketFrameHeader::OpCode current_reading_opcode_ =
+      WebSocketFrameHeader::kOpCodeText;
+  WebSocketFrameHeader::OpCode current_writing_opcode_ =
+      WebSocketFrameHeader::kOpCodeText;
   std::unique_ptr<WebSocketDeflatePredictor> predictor_;
 
   // User callback saved for asynchronous reads.
diff --git a/net/websockets/websocket_deflate_stream_test.cc b/net/websockets/websocket_deflate_stream_test.cc
index 2e828cd..45736233 100644
--- a/net/websockets/websocket_deflate_stream_test.cc
+++ b/net/websockets/websocket_deflate_stream_test.cc
@@ -94,7 +94,7 @@
 //  - RecordWrittenDataFrame is called before writing the frame.
 class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor {
  public:
-  WebSocketDeflatePredictorMock() : result_(DEFLATE) {}
+  WebSocketDeflatePredictorMock() = default;
 
   WebSocketDeflatePredictorMock(const WebSocketDeflatePredictorMock&) = delete;
   WebSocketDeflatePredictorMock& operator=(
@@ -185,7 +185,7 @@
   }
 
  private:
-  Result result_;
+  Result result_ = DEFLATE;
   // Data frames which will be recorded by |RecordInputFrames|.
   // Pushed by |AddFrameToBeInput| and popped and verified by
   // |RecordInputFrames|.
diff --git a/net/websockets/websocket_deflater.cc b/net/websockets/websocket_deflater.cc
index 8f93a014..983398dd6 100644
--- a/net/websockets/websocket_deflater.cc
+++ b/net/websockets/websocket_deflater.cc
@@ -15,8 +15,7 @@
 
 namespace net {
 
-WebSocketDeflater::WebSocketDeflater(ContextTakeOverMode mode)
-    : mode_(mode), are_bytes_added_(false) {}
+WebSocketDeflater::WebSocketDeflater(ContextTakeOverMode mode) : mode_(mode) {}
 
 WebSocketDeflater::~WebSocketDeflater() {
   if (stream_) {
diff --git a/net/websockets/websocket_deflater.h b/net/websockets/websocket_deflater.h
index 1b899fe..ab99aef 100644
--- a/net/websockets/websocket_deflater.h
+++ b/net/websockets/websocket_deflater.h
@@ -71,7 +71,7 @@
   base::circular_deque<char> buffer_;
   std::vector<char> fixed_buffer_;
   // true if bytes were added after last Finish().
-  bool are_bytes_added_;
+  bool are_bytes_added_ = false;
 };
 
 }  // namespace net
diff --git a/net/websockets/websocket_end_to_end_test.cc b/net/websockets/websocket_end_to_end_test.cc
index 2871ba0..2eb011c 100644
--- a/net/websockets/websocket_end_to_end_test.cc
+++ b/net/websockets/websocket_end_to_end_test.cc
@@ -159,7 +159,7 @@
   void QuitNestedEventLoop();
 
   // failed_ is true if the handshake failed (ie. OnFailChannel was called).
-  bool failed_;
+  bool failed_ = false;
   std::unique_ptr<WebSocketHandshakeResponseInfo> response_;
   std::string selected_subprotocol_;
   std::string extensions_;
@@ -167,8 +167,7 @@
   base::RunLoop run_loop_;
 };
 
-ConnectTestingEventInterface::ConnectTestingEventInterface() : failed_(false) {
-}
+ConnectTestingEventInterface::ConnectTestingEventInterface() = default;
 
 void ConnectTestingEventInterface::WaitForResponse() {
   run_loop_.Run();
diff --git a/net/websockets/websocket_frame.cc b/net/websockets/websocket_frame.cc
index 6995fae05..1f931e6c 100644
--- a/net/websockets/websocket_frame.cc
+++ b/net/websockets/websocket_frame.cc
@@ -79,7 +79,7 @@
 
 WebSocketFrame::~WebSocketFrame() = default;
 
-WebSocketFrameChunk::WebSocketFrameChunk() : final_chunk(false) {}
+WebSocketFrameChunk::WebSocketFrameChunk() = default;
 
 WebSocketFrameChunk::~WebSocketFrameChunk() = default;
 
diff --git a/net/websockets/websocket_frame.h b/net/websockets/websocket_frame.h
index e158b94..a6ca5ab4 100644
--- a/net/websockets/websocket_frame.h
+++ b/net/websockets/websocket_frame.h
@@ -142,7 +142,7 @@
   std::unique_ptr<WebSocketFrameHeader> header;
 
   // Indicates this part is the last chunk of a frame.
-  bool final_chunk;
+  bool final_chunk = false;
 
   // |payload| is always unmasked even if the frame is masked. |payload| might
   // be empty in the first chunk.
diff --git a/net/websockets/websocket_frame_parser.cc b/net/websockets/websocket_frame_parser.cc
index fe5f619..52c89b95 100644
--- a/net/websockets/websocket_frame_parser.cc
+++ b/net/websockets/websocket_frame_parser.cc
@@ -36,8 +36,7 @@
 
 namespace net {
 
-WebSocketFrameParser::WebSocketFrameParser()
-    : frame_offset_(0), websocket_error_(kWebSocketNormalClosure) {}
+WebSocketFrameParser::WebSocketFrameParser() = default;
 
 WebSocketFrameParser::~WebSocketFrameParser() = default;
 
diff --git a/net/websockets/websocket_frame_parser.h b/net/websockets/websocket_frame_parser.h
index d1a60968..bcffd1b9 100644
--- a/net/websockets/websocket_frame_parser.h
+++ b/net/websockets/websocket_frame_parser.h
@@ -81,9 +81,9 @@
   std::unique_ptr<WebSocketFrameHeader> current_frame_header_;
 
   // Amount of payload data read so far for the current frame.
-  uint64_t frame_offset_;
+  uint64_t frame_offset_ = 0;
 
-  WebSocketError websocket_error_;
+  WebSocketError websocket_error_ = kWebSocketNormalClosure;
 };
 
 }  // namespace net
diff --git a/net/websockets/websocket_http2_handshake_stream.cc b/net/websockets/websocket_http2_handshake_stream.cc
index c0d9c83..0f3e465 100644
--- a/net/websockets/websocket_http2_handshake_stream.cc
+++ b/net/websockets/websocket_http2_handshake_stream.cc
@@ -46,17 +46,13 @@
     std::vector<std::string> requested_extensions,
     WebSocketStreamRequestAPI* request,
     std::set<std::string> dns_aliases)
-    : result_(HandshakeResult::HTTP2_INCOMPLETE),
-      session_(session),
+    : session_(session),
       connect_delegate_(connect_delegate),
       http_response_info_(nullptr),
       requested_sub_protocols_(requested_sub_protocols),
       requested_extensions_(requested_extensions),
       stream_request_(request),
       request_info_(nullptr),
-      stream_closed_(false),
-      stream_error_(OK),
-      response_headers_complete_(false),
       dns_aliases_(std::move(dns_aliases)) {
   DCHECK(connect_delegate);
   DCHECK(request);
diff --git a/net/websockets/websocket_http2_handshake_stream.h b/net/websockets/websocket_http2_handshake_stream.h
index d0a425a..d9ed31cf 100644
--- a/net/websockets/websocket_http2_handshake_stream.h
+++ b/net/websockets/websocket_http2_handshake_stream.h
@@ -127,7 +127,7 @@
                  int net_error,
                  absl::optional<int> response_code);
 
-  HandshakeResult result_;
+  HandshakeResult result_ = HandshakeResult::HTTP2_INCOMPLETE;
 
   // The connection to open the Websocket stream on.
   base::WeakPtr<SpdySession> session_;
@@ -165,14 +165,14 @@
   std::unique_ptr<WebSocketSpdyStreamAdapter> stream_adapter_;
 
   // True if |stream_| has been created then closed.
-  bool stream_closed_;
+  bool stream_closed_ = false;
 
   // The error code corresponding to the reason for closing the stream.
   // Only meaningful if |stream_closed_| is true.
-  int stream_error_;
+  int stream_error_ = OK;
 
   // True if complete response headers have been received.
-  bool response_headers_complete_;
+  bool response_headers_complete_ = false;
 
   // Save callback provided in asynchronous HttpStream methods.
   CompletionOnceCallback callback_;
diff --git a/net/websockets/websocket_inflater.cc b/net/websockets/websocket_inflater.cc
index c150b5f..9244754 100644
--- a/net/websockets/websocket_inflater.cc
+++ b/net/websockets/websocket_inflater.cc
@@ -166,9 +166,8 @@
 
 WebSocketInflater::OutputBuffer::OutputBuffer(size_t capacity)
     : capacity_(capacity),
-      buffer_(capacity_ + 1),  // 1 for sentinel
-      head_(0),
-      tail_(0) {}
+      buffer_(capacity_ + 1)  // 1 for sentinel
+{}
 
 WebSocketInflater::OutputBuffer::~OutputBuffer() = default;
 
@@ -218,7 +217,7 @@
 }
 
 WebSocketInflater::InputQueue::InputQueue(size_t capacity)
-    : capacity_(capacity), head_of_first_buffer_(0), tail_of_last_buffer_(0) {}
+    : capacity_(capacity) {}
 
 WebSocketInflater::InputQueue::~InputQueue() = default;
 
diff --git a/net/websockets/websocket_inflater.h b/net/websockets/websocket_inflater.h
index 7737440..540aeac 100644
--- a/net/websockets/websocket_inflater.h
+++ b/net/websockets/websocket_inflater.h
@@ -89,8 +89,8 @@
 
     const size_t capacity_;
     std::vector<char> buffer_;
-    size_t head_;
-    size_t tail_;
+    size_t head_ = 0;
+    size_t tail_ = 0;
   };
 
   class InputQueue {
@@ -114,8 +114,8 @@
     size_t PushToLastBuffer(const char* data, size_t size);
 
     const size_t capacity_;
-    size_t head_of_first_buffer_;
-    size_t tail_of_last_buffer_;
+    size_t head_of_first_buffer_ = 0;
+    size_t tail_of_last_buffer_ = 0;
     base::circular_deque<scoped_refptr<IOBufferWithSize>> buffers_;
   };
 
diff --git a/net/websockets/websocket_stream_create_test_base.cc b/net/websockets/websocket_stream_create_test_base.cc
index 26d2ede4..ee54346 100644
--- a/net/websockets/websocket_stream_create_test_base.cc
+++ b/net/websockets/websocket_stream_create_test_base.cc
@@ -93,7 +93,7 @@
 };
 
 WebSocketStreamCreateTestBase::WebSocketStreamCreateTestBase()
-    : has_failed_(false), ssl_fatal_(false), url_request_(nullptr) {}
+    : url_request_(nullptr) {}
 
 WebSocketStreamCreateTestBase::~WebSocketStreamCreateTestBase() = default;
 
diff --git a/net/websockets/websocket_stream_create_test_base.h b/net/websockets/websocket_stream_create_test_base.h
index 380cad7..a57c6f26 100644
--- a/net/websockets/websocket_stream_create_test_base.h
+++ b/net/websockets/websocket_stream_create_test_base.h
@@ -83,13 +83,13 @@
   // Only set if the connection failed.
   std::string failure_message_;
   int failure_response_code_ = -1;
-  bool has_failed_;
+  bool has_failed_ = false;
   std::unique_ptr<WebSocketHandshakeRequestInfo> request_info_;
   std::unique_ptr<WebSocketHandshakeResponseInfo> response_info_;
   std::unique_ptr<WebSocketEventInterface::SSLErrorCallbacks>
       ssl_error_callbacks_;
   SSLInfo ssl_info_;
-  bool ssl_fatal_;
+  bool ssl_fatal_ = false;
   raw_ptr<URLRequest> url_request_;
   AuthChallengeInfo auth_challenge_info_;
   base::OnceCallback<void(const AuthCredentials*)> on_auth_required_callback_;
diff --git a/net/websockets/websocket_stream_test.cc b/net/websockets/websocket_stream_test.cc
index be0a840..a7b9fe87 100644
--- a/net/websockets/websocket_stream_test.cc
+++ b/net/websockets/websocket_stream_test.cc
@@ -101,11 +101,7 @@
 class WebSocketStreamCreateTest : public TestWithParam<HandshakeStreamType>,
                                   public WebSocketStreamCreateTestBase {
  protected:
-  WebSocketStreamCreateTest()
-      : stream_type_(GetParam()),
-        http2_response_status_("200"),
-        reset_websocket_http2_stream_(false),
-        sequence_number_(0) {
+  WebSocketStreamCreateTest() : stream_type_(GetParam()) {
     // Make sure these tests all pass with connection partitioning enabled. The
     // disabled case is less interesting, and is tested more directly at lower
     // layers.
@@ -398,12 +394,12 @@
 
   std::unique_ptr<base::OneShotTimer> timer_;
   std::string additional_data_;
-  const char* http2_response_status_;
-  bool reset_websocket_http2_stream_;
+  const char* http2_response_status_ = "200";
+  bool reset_websocket_http2_stream_ = false;
   SpdyTestUtil spdy_util_;
   NetLogWithSource log_;
 
-  int sequence_number_;
+  int sequence_number_ = 0;
 
   // Store mock HTTP/2 data.
   std::vector<spdy::SpdySerializedFrame> frames_;
diff --git a/pdf/pdf_view_plugin_base_unittest.cc b/pdf/pdf_view_plugin_base_unittest.cc
index 6858676..90185ae 100644
--- a/pdf/pdf_view_plugin_base_unittest.cc
+++ b/pdf/pdf_view_plugin_base_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/time/time.h"
 #include "base/values.h"
 #include "pdf/accessibility_structs.h"
-#include "pdf/content_restriction.h"
 #include "pdf/document_attachment_info.h"
 #include "pdf/document_layout.h"
 #include "pdf/document_metadata.h"
@@ -39,14 +38,9 @@
 
 namespace {
 
-using blink::WebPrintParams;
 using ::testing::ByMove;
 using ::testing::ElementsAre;
-using ::testing::Field;
-using ::testing::InSequence;
 using ::testing::IsEmpty;
-using ::testing::IsFalse;
-using ::testing::IsTrue;
 using ::testing::NiceMock;
 using ::testing::Return;
 using ::testing::SaveArg;
@@ -571,159 +565,4 @@
   EXPECT_EQ(gfx::Point(-300, -56), viewport_info.scroll);
 }
 
-TEST_F(PdfViewPluginBaseWithEngineTest, NormalPrinting) {
-  WebPrintParams params;
-  const std::vector<int> kPageNumbers = {0};
-
-  auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine());
-  engine->SetPermissions({DocumentPermission::kPrintHighQuality,
-                          DocumentPermission::kPrintLowQuality});
-
-  InSequence sequence;
-  EXPECT_CALL(*engine,
-              PrintPages(kPageNumbers,
-                         Field(&WebPrintParams::rasterize_pdf, IsFalse())))
-      .Times(1);
-  EXPECT_CALL(
-      *engine,
-      PrintPages(kPageNumbers, Field(&WebPrintParams::rasterize_pdf, IsTrue())))
-      .Times(1);
-
-  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
-            fake_plugin_.PrintBegin(params));
-  fake_plugin_.PrintPages(kPageNumbers);
-  fake_plugin_.PrintEnd();
-
-  params.rasterize_pdf = true;
-  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
-            fake_plugin_.PrintBegin(params));
-  fake_plugin_.PrintPages(kPageNumbers);
-  fake_plugin_.PrintEnd();
-}
-
-// Regression test for crbug.com/1307219.
-TEST_F(PdfViewPluginBaseWithEngineTest, LowQualityPrinting) {
-  WebPrintParams params;
-  const std::vector<int> kPageNumbers = {0};
-
-  auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine());
-  engine->SetPermissions({DocumentPermission::kPrintLowQuality});
-
-  EXPECT_CALL(
-      *engine,
-      PrintPages(kPageNumbers, Field(&WebPrintParams::rasterize_pdf, IsTrue())))
-      .Times(2);
-
-  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
-            fake_plugin_.PrintBegin(params));
-  fake_plugin_.PrintPages(kPageNumbers);
-  fake_plugin_.PrintEnd();
-
-  params.rasterize_pdf = true;
-  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
-            fake_plugin_.PrintBegin(params));
-  fake_plugin_.PrintPages(kPageNumbers);
-  fake_plugin_.PrintEnd();
-}
-
-TEST_F(PdfViewPluginBaseWithEngineTest, NoPrinting) {
-  WebPrintParams params;
-
-  auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine());
-  engine->SetPermissions({});
-
-  EXPECT_EQ(0, fake_plugin_.PrintBegin(params));
-
-  params.rasterize_pdf = true;
-  EXPECT_EQ(0, fake_plugin_.PrintBegin(params));
-}
-
-TEST_F(PdfViewPluginBaseWithEngineTest, GetContentRestrictions) {
-  auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine());
-  static constexpr int kContentRestrictionCutPaste =
-      kContentRestrictionCut | kContentRestrictionPaste;
-
-  // Test engine without any permissions.
-  engine->SetPermissions({});
-
-  int content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy |
-                kContentRestrictionPrint,
-            content_restrictions);
-
-  // Test engine with only copy permission.
-  engine->SetPermissions({DocumentPermission::kCopy});
-
-  content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionPrint,
-            content_restrictions);
-
-  // Test engine with only print low quality permission.
-  engine->SetPermissions({DocumentPermission::kPrintLowQuality});
-
-  content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy,
-            content_restrictions);
-
-  // Test engine with both copy and print low quality permissions.
-  engine->SetPermissions(
-      {DocumentPermission::kCopy, DocumentPermission::kPrintLowQuality});
-
-  content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste, content_restrictions);
-
-  // Test engine with print high and low quality permissions.
-  engine->SetPermissions({DocumentPermission::kPrintHighQuality,
-                          DocumentPermission::kPrintLowQuality});
-
-  content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste | kContentRestrictionCopy,
-            content_restrictions);
-
-  // Test engine with copy, print high and low quality permissions.
-  engine->SetPermissions({DocumentPermission::kCopy,
-                          DocumentPermission::kPrintHighQuality,
-                          DocumentPermission::kPrintLowQuality});
-
-  content_restrictions = fake_plugin_.GetContentRestrictions();
-  EXPECT_EQ(kContentRestrictionCutPaste, content_restrictions);
-}
-
-TEST_F(PdfViewPluginBaseWithEngineTest, GetAccessibilityDocInfo) {
-  auto* engine = static_cast<TestPDFiumEngine*>(fake_plugin_.engine());
-
-  // Test engine without any permissions.
-  engine->SetPermissions({});
-
-  AccessibilityDocInfo doc_info = fake_plugin_.GetAccessibilityDocInfo();
-  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
-  EXPECT_FALSE(doc_info.text_accessible);
-  EXPECT_FALSE(doc_info.text_copyable);
-
-  // Test engine with only copy permission.
-  engine->SetPermissions({DocumentPermission::kCopy});
-
-  doc_info = fake_plugin_.GetAccessibilityDocInfo();
-  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
-  EXPECT_FALSE(doc_info.text_accessible);
-  EXPECT_TRUE(doc_info.text_copyable);
-
-  // Test engine with only copy accessible permission.
-  engine->SetPermissions({DocumentPermission::kCopyAccessible});
-
-  doc_info = fake_plugin_.GetAccessibilityDocInfo();
-  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
-  EXPECT_TRUE(doc_info.text_accessible);
-  EXPECT_FALSE(doc_info.text_copyable);
-
-  // Test engine with both copy and copy accessible permission.
-  engine->SetPermissions(
-      {DocumentPermission::kCopy, DocumentPermission::kCopyAccessible});
-
-  doc_info = fake_plugin_.GetAccessibilityDocInfo();
-  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
-  EXPECT_TRUE(doc_info.text_accessible);
-  EXPECT_TRUE(doc_info.text_copyable);
-}
-
 }  // namespace chrome_pdf
diff --git a/pdf/pdf_view_web_plugin_unittest.cc b/pdf/pdf_view_web_plugin_unittest.cc
index cbd366b7..dbe3a9a 100644
--- a/pdf/pdf_view_web_plugin_unittest.cc
+++ b/pdf/pdf_view_web_plugin_unittest.cc
@@ -4,6 +4,8 @@
 
 #include "pdf/pdf_view_web_plugin.h"
 
+#include <stdint.h>
+
 #include <functional>
 #include <memory>
 #include <string>
@@ -26,6 +28,7 @@
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
 #include "net/cookies/site_for_cookies.h"
+#include "pdf/accessibility_structs.h"
 #include "pdf/buildflags.h"
 #include "pdf/content_restriction.h"
 #include "pdf/mojom/pdf.mojom.h"
@@ -34,6 +37,7 @@
 #include "pdf/pdf_view_plugin_base.h"
 #include "pdf/test/test_helpers.h"
 #include "pdf/test/test_pdfium_engine.h"
+#include "printing/metafile_skia.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,6 +59,7 @@
 #include "third_party/blink/public/web/web_associated_url_loader_client.h"
 #include "third_party/blink/public/web/web_plugin_container.h"
 #include "third_party/blink/public/web/web_plugin_params.h"
+#include "third_party/blink/public/web/web_print_params.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -80,11 +85,14 @@
 namespace {
 
 using ::testing::AnyNumber;
+using ::testing::ElementsAre;
 using ::testing::ElementsAreArray;
 using ::testing::Eq;
 using ::testing::InSequence;
 using ::testing::Invoke;
 using ::testing::IsEmpty;
+using ::testing::IsFalse;
+using ::testing::IsTrue;
 using ::testing::MockFunction;
 using ::testing::NiceMock;
 using ::testing::Pointwise;
@@ -816,6 +824,118 @@
   plugin_->EnableAccessibility();
 }
 
+TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithNoPermissions) {
+  EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
+                kContentRestrictionPaste | kContentRestrictionPrint,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
+      .WillRepeatedly(Return(true));
+
+  EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste |
+                kContentRestrictionPrint,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintLowQualityAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
+                kContentRestrictionPaste,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest,
+       GetContentRestrictionsWithCopyAndPrintLowQualityAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithPrintAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  EXPECT_EQ(kContentRestrictionCopy | kContentRestrictionCut |
+                kContentRestrictionPaste,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest, GetContentRestrictionsWithCopyAndPrintAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  EXPECT_EQ(kContentRestrictionCut | kContentRestrictionPaste,
+            plugin_->GetContentRestrictions());
+}
+
+TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithNoPermissions) {
+  AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
+
+  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
+  EXPECT_FALSE(doc_info.text_accessible);
+  EXPECT_FALSE(doc_info.text_copyable);
+}
+
+TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
+      .WillRepeatedly(Return(true));
+
+  AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
+
+  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
+  EXPECT_FALSE(doc_info.text_accessible);
+  EXPECT_TRUE(doc_info.text_copyable);
+}
+
+TEST_F(PdfViewWebPluginTest, GetAccessibilityDocInfoWithCopyAccessibleAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
+      .WillRepeatedly(Return(true));
+
+  AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
+
+  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
+  EXPECT_TRUE(doc_info.text_accessible);
+  EXPECT_FALSE(doc_info.text_copyable);
+}
+
+TEST_F(PdfViewWebPluginTest,
+       GetAccessibilityDocInfoWithCopyAndCopyAccessibleAllowed) {
+  EXPECT_CALL(*engine_ptr_, HasPermission).WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopy))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kCopyAccessible))
+      .WillRepeatedly(Return(true));
+
+  AccessibilityDocInfo doc_info = plugin_->GetAccessibilityDocInfo();
+
+  EXPECT_EQ(TestPDFiumEngine::kPageNumber, doc_info.page_count);
+  EXPECT_TRUE(doc_info.text_accessible);
+  EXPECT_TRUE(doc_info.text_copyable);
+}
+
 TEST_F(PdfViewWebPluginTest, UpdateGeometrySetsPluginRect) {
   EXPECT_CALL(*engine_ptr_, ZoomUpdated(2.0f));
   TestUpdateGeometrySetsPluginRect(
@@ -1729,6 +1849,107 @@
   SubmitFailingForm("https://wwww.example.com");
 }
 
+class PdfViewWebPluginPrintTest : public PdfViewWebPluginTest {
+ protected:
+  void SetUp() override {
+    PdfViewWebPluginTest::SetUp();
+
+    // Size must be at least 1 for conversion to `SkMemoryStream`.
+    ON_CALL(*engine_ptr_, PrintPages)
+        .WillByDefault(Return(std::vector<uint8_t>(1)));
+
+    canvas_.sk_canvas()->SetPrintingMetafile(&metafile_);
+  }
+
+  printing::MetafileSkia metafile_;
+};
+
+TEST_F(PdfViewWebPluginPrintTest, HighQuality) {
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
+            plugin_->PrintBegin(blink::WebPrintParams()));
+
+  EXPECT_CALL(
+      *engine_ptr_,
+      PrintPages(ElementsAre(0),
+                 Field(&blink::WebPrintParams::rasterize_pdf, IsFalse())));
+  plugin_->PrintPage(0, canvas_.sk_canvas());
+  plugin_->PrintEnd();
+}
+
+TEST_F(PdfViewWebPluginPrintTest, HighQualityRasterized) {
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(true));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  blink::WebPrintParams params;
+  params.rasterize_pdf = true;
+  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
+            plugin_->PrintBegin(params));
+
+  EXPECT_CALL(
+      *engine_ptr_,
+      PrintPages(ElementsAre(0),
+                 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
+  plugin_->PrintPage(0, canvas_.sk_canvas());
+  plugin_->PrintEnd();
+}
+
+// Regression test for crbug.com/1307219.
+TEST_F(PdfViewWebPluginPrintTest, LowQuality) {
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
+            plugin_->PrintBegin(blink::WebPrintParams()));
+
+  EXPECT_CALL(
+      *engine_ptr_,
+      PrintPages(ElementsAre(0),
+                 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
+  plugin_->PrintPage(0, canvas_.sk_canvas());
+  plugin_->PrintEnd();
+}
+
+// Regression test for crbug.com/1307219.
+TEST_F(PdfViewWebPluginPrintTest, LowQualityRasterized) {
+  EXPECT_CALL(*engine_ptr_,
+              HasPermission(DocumentPermission::kPrintHighQuality))
+      .WillRepeatedly(Return(false));
+  EXPECT_CALL(*engine_ptr_, HasPermission(DocumentPermission::kPrintLowQuality))
+      .WillRepeatedly(Return(true));
+
+  blink::WebPrintParams params;
+  params.rasterize_pdf = true;
+  ASSERT_EQ(static_cast<int>(TestPDFiumEngine::kPageNumber),
+            plugin_->PrintBegin(params));
+
+  EXPECT_CALL(
+      *engine_ptr_,
+      PrintPages(ElementsAre(0),
+                 Field(&blink::WebPrintParams::rasterize_pdf, IsTrue())));
+  plugin_->PrintPage(0, canvas_.sk_canvas());
+  plugin_->PrintEnd();
+}
+
+TEST_F(PdfViewWebPluginPrintTest, Disabled) {
+  EXPECT_EQ(0, plugin_->PrintBegin(blink::WebPrintParams()));
+}
+
+TEST_F(PdfViewWebPluginPrintTest, DisabledRasterized) {
+  blink::WebPrintParams params;
+  params.rasterize_pdf = true;
+  EXPECT_EQ(0, plugin_->PrintBegin(params));
+}
+
 class PdfViewWebPluginPrintPreviewTest : public PdfViewWebPluginTest {
  protected:
   void SetUpClient() override {
diff --git a/pdf/test/test_pdfium_engine.cc b/pdf/test/test_pdfium_engine.cc
index b789fa9e..34fc392 100644
--- a/pdf/test/test_pdfium_engine.cc
+++ b/pdf/test/test_pdfium_engine.cc
@@ -11,8 +11,6 @@
 #include <vector>
 
 #include "base/check_op.h"
-#include "base/containers/contains.h"
-#include "base/containers/flat_set.h"
 #include "base/values.h"
 #include "pdf/document_attachment_info.h"
 #include "pdf/document_metadata.h"
@@ -36,10 +34,6 @@
 
 TestPDFiumEngine::~TestPDFiumEngine() = default;
 
-bool TestPDFiumEngine::HasPermission(DocumentPermission permission) const {
-  return base::Contains(permissions_, permission);
-}
-
 const std::vector<DocumentAttachmentInfo>&
 TestPDFiumEngine::GetDocumentAttachmentInfoList() const {
   return doc_attachment_info_list_;
@@ -71,12 +65,4 @@
   return std::vector<uint8_t>(std::begin(kSaveData), std::end(kSaveData));
 }
 
-void TestPDFiumEngine::SetPermissions(
-    const std::vector<DocumentPermission>& permissions) {
-  permissions_.clear();
-
-  for (auto& permission : permissions)
-    permissions_.insert(permission);
-}
-
 }  // namespace chrome_pdf
diff --git a/pdf/test/test_pdfium_engine.h b/pdf/test/test_pdfium_engine.h
index 705dd36..5aa2569 100644
--- a/pdf/test/test_pdfium_engine.h
+++ b/pdf/test/test_pdfium_engine.h
@@ -9,7 +9,6 @@
 
 #include <vector>
 
-#include "base/containers/flat_set.h"
 #include "base/values.h"
 #include "pdf/document_attachment_info.h"
 #include "pdf/document_metadata.h"
@@ -60,8 +59,7 @@
 
   MOCK_METHOD(std::vector<uint8_t>,
               PrintPages,
-              (const std::vector<int>& page_numbers,
-               const blink::WebPrintParams& print_params),
+              (const std::vector<int>&, const blink::WebPrintParams&),
               (override));
 
   MOCK_METHOD(void, ZoomUpdated, (double), (override));
@@ -71,7 +69,7 @@
               (const DocumentLayout::Options&),
               (override));
 
-  bool HasPermission(DocumentPermission permission) const override;
+  MOCK_METHOD(bool, HasPermission, (DocumentPermission), (const override));
 
   const std::vector<DocumentAttachmentInfo>& GetDocumentAttachmentInfoList()
       const override;
@@ -95,8 +93,6 @@
 
   MOCK_METHOD(void, SetCaretPosition, (const gfx::Point&), (override));
 
-  void SetPermissions(const std::vector<DocumentPermission>& permissions);
-
   MOCK_METHOD(void, OnDocumentCanceled, (), (override));
 
  protected:
@@ -110,8 +106,6 @@
   std::vector<DocumentAttachmentInfo> doc_attachment_info_list_;
 
   DocumentMetadata metadata_;
-
-  base::flat_set<DocumentPermission> permissions_;
 };
 
 }  // namespace chrome_pdf
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index f711104..3b91be2 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -8274,7 +8274,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8784,7 +8784,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 0c437d7..2a1f7649 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46249,7 +46249,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46759,7 +46759,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47273,7 +47273,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47783,7 +47783,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48365,7 +48365,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48875,7 +48875,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49457,7 +49457,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49967,7 +49967,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M102",
-              "revision": "version:102.0.5005.113"
+              "revision": "version:102.0.5005.124"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index e736a5c..e4905e4 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -3169,6 +3169,34 @@
         "test_id_prefix": "ninja://ash/components:ash_components_unittests/"
       },
       {
+        "args": [
+          "--enable-pixel-output-in-tests",
+          "--git-revision=${got_revision}"
+        ],
+        "experiment_percentage": 100,
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-18.04"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "ash_pixeltests",
+        "test_id_prefix": "ninja://ash:ash_pixeltests/"
+      },
+      {
         "isolate_profile_data": true,
         "merge": {
           "args": [],
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index aee181d..0d293619 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -105575,44 +105575,5 @@
         "test_id_prefix": "ninja://:blink_web_tests/"
       }
     ]
-  },
-  "win7-blink-rel-dummy": {
-    "isolated_scripts": [
-      {
-        "args": [
-          "--num-retries=3",
-          "--git-revision=${got_revision}"
-        ],
-        "isolate_name": "blink_web_tests",
-        "merge": {
-          "args": [
-            "--verbose"
-          ],
-          "script": "//third_party/blink/tools/merge_web_test_results.py"
-        },
-        "name": "blink_web_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "resultdb": {
-          "enable": true
-        },
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "os": "Windows-7-SP1"
-            }
-          ],
-          "hard_timeout": 900,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 12
-        },
-        "test_id_prefix": "ninja://:blink_web_tests/"
-      }
-    ]
   }
 }
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json
index 456fbb2..4879df7 100644
--- a/testing/buildbot/chromium.win.json
+++ b/testing/buildbot/chromium.win.json
@@ -10164,35 +10164,6 @@
       },
       {
         "args": [
-          "--num-retries=3",
-          "--git-revision=${got_revision}"
-        ],
-        "isolate_name": "blink_web_tests",
-        "merge": {
-          "args": [
-            "--verbose"
-          ],
-          "script": "//third_party/blink/tools/merge_web_test_results.py"
-        },
-        "name": "blink_web_tests",
-        "precommit_args": [
-          "--gerrit-issue=${patch_issue}",
-          "--gerrit-patchset=${patch_set}",
-          "--buildbucket-id=${buildbucket_build_id}"
-        ],
-        "resultdb": {
-          "enable": true
-        },
-        "results_handler": "layout tests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
-          "shards": 12
-        },
-        "test_id_prefix": "ninja://:blink_web_tests/"
-      },
-      {
-        "args": [
           "--test-type=integration"
         ],
         "check_flakiness_for_new_tests": false,
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index c64656f..1af0e5e 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -1604,7 +1604,6 @@
         'mac10.15-blink-rel-dummy',
         'mac11.0-blink-rel-dummy',
         'mac11.0.arm64-blink-rel-dummy',
-        'win7-blink-rel-dummy',
         'win10.20h2-blink-rel-dummy',
         'win11-blink-rel-dummy',
     ]
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index d4766bb6..49f33be 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -209,6 +209,10 @@
     "label": "//ash:ash_unittests",
     "type": "windowed_test_launcher",
   },
+  "ash_pixeltests": {
+    "label": "//ash:ash_pixeltests",
+    "type": "windowed_test_launcher",
+  },
   "aura_unittests": {
     "label": "//ui/aura:aura_unittests",
     "type": "windowed_test_launcher",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 9af486f..24ee6408 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -229,6 +229,7 @@
   'blink_web_tests': {
     'remove_from': [
       'Win 7 Tests x64 (1)',  # 64-bit win is unsupported by the layout tests.
+      'Win7 Tests (1)',
       'Win10 Tests x64 (dbg)',
     ],
     'modifications': {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 003abd2..dc2e9be 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -320,6 +320,18 @@
       },
     },
 
+    'ash_pixel_gtests': {
+      'ash_pixeltests': {
+         'args': [
+          '--enable-pixel-output-in-tests',
+        ],
+        'experiment_percentage': 100,
+        'mixins': [
+          'skia_gold_test',
+        ],
+      },
+    },
+
     'aura_gtests': {
       'aura_unittests': {},
       'compositor_unittests': {},
@@ -6603,6 +6615,7 @@
       'linux_chromeos_browser_tests_require_lacros',
       'linux_flavor_specific_chromium_gtests',
       'non_android_chromium_gtests',
+      'ash_pixel_gtests',
     ],
 
     'linux_viz_gtests': [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 2105316..bd0b870 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -515,7 +515,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.113',
+          'revision': 'version:102.0.5005.124',
         }
       ],
     },
@@ -659,7 +659,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.113',
+          'revision': 'version:102.0.5005.124',
         }
       ],
     },
@@ -803,7 +803,7 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M102',
-          'revision': 'version:102.0.5005.113',
+          'revision': 'version:102.0.5005.124',
         }
       ],
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 1fd98ab3..2ef0ebf2 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -3810,19 +3810,6 @@
           'isolated_scripts': 'chromium_webkit_isolated_scripts',
         },
       },
-      'win7-blink-rel-dummy': {
-        'swarming': {
-          'dimension_sets': [
-            {
-              'os': 'Windows-7-SP1',
-            },
-          ],
-          'hard_timeout': 900,
-        },
-        'test_suites': {
-          'isolated_scripts': 'chromium_webkit_isolated_scripts',
-        },
-      },
     },
   },
   {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 278bb5c..6e5b285 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -7283,7 +7283,7 @@
                 {
                     "name": "Enabled",
                     "params": {
-                        "segment_ids_allowed_for_reporting": "4,5,6,11,12,16"
+                        "segment_ids_allowed_for_reporting": "4,5,6,10,11,12,16"
                     },
                     "enable_features": [
                         "SegmentationStructuredMetrics"
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index a594aeb..d7b25c6 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -2659,6 +2659,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbcursor_idbindex_idbobjectstore.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbindex_idbobjectstore.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_idbindex_idbobjectstore.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediastreamtrack_string.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_mediastreamtrack_string.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_path2d_string.cc",
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
index 716e8cf..70a2a8d 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h
@@ -213,11 +213,13 @@
   // `callback`.
   using VideoFrameCopyCompletedCallback =
       base::OnceCallback<void(scoped_refptr<media::VideoFrame>)>;
-  virtual void CopyRenderingResultsToVideoFrame(
+  virtual bool CopyRenderingResultsToVideoFrame(
       WebGraphicsContext3DVideoFramePool* frame_pool,
       SourceDrawingBuffer,
       const gfx::ColorSpace& dst_color_space,
-      VideoFrameCopyCompletedCallback& callback) {}
+      VideoFrameCopyCompletedCallback callback) {
+    return false;
+  }
 
   virtual cc::Layer* CcLayer() const { return nullptr; }
 
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 1cad129..0e7de0b 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -730,7 +730,10 @@
     if (!listener->NeedsNewFrame())
       continue;
 
-    auto callback = listener->GetNewFrameCallback();
+    // Split the listener's callback so that it can be used with both the one
+    // copy path and fallback two copy path below.
+    auto split_callback =
+        base::SplitOnceCallback(listener->GetNewFrameCallback());
     const bool can_discard_alpha = listener->CanDiscardAlpha();
 
     // First attempt to copy directly from the rendering context to a video
@@ -738,12 +741,13 @@
     // where GetSourceImageForCanvasInternal is zero-copy, this is superfluous).
     if (context_ && can_discard_alpha &&
         base::FeatureList::IsEnabled(kOneCopyCanvasCapture)) {
-      context_->CopyRenderingResultsToVideoFrame(
-          copier_->GetAcceleratedVideoFramePool(
-              SharedGpuContext::ContextProviderWrapper()),
-          kBackBuffer, gfx::ColorSpace::CreateREC709(), callback);
-      if (!callback)
+      if (context_->CopyRenderingResultsToVideoFrame(
+              copier_->GetAcceleratedVideoFramePool(
+                  SharedGpuContext::ContextProviderWrapper()),
+              kBackBuffer, gfx::ColorSpace::CreateREC709(),
+              std::move(split_callback.first))) {
         continue;
+      }
     }
 
     // If that fails, then create a StaticBitmapImage for the contents of
@@ -760,7 +764,7 @@
     // need a context_provider that has a RasterInterface available.
     copier_->Convert(source_image, can_discard_alpha,
                      SharedGpuContext::ContextProviderWrapper(),
-                     std::move(callback));
+                     std::move(split_callback.second));
   }
 }
 
diff --git a/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js b/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js
index f3738dc1..371591d 100644
--- a/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js
+++ b/third_party/blink/renderer/core/html/forms/resources/calendar_picker.js
@@ -2244,7 +2244,8 @@
    */
   onWindowTouchEnd(event) {
     this._thumbStyleTopAnimator = new TransitionAnimator();
-    this._thumbStyleTopAnimator.step = this.onThumbStyleTopAnimationStep;
+    this._thumbStyleTopAnimator.step =
+        this.onThumbStyleTopAnimationStep.bind(this);
     this._thumbStyleTopAnimator.setFrom(this.thumb.offsetTop);
     this._thumbStyleTopAnimator.setTo((this._height - this._thumbHeight) / 2);
     this._thumbStyleTopAnimator.timingFunction =
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc
index 3c5d7f4f..fa373a5 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -87,6 +87,7 @@
 #include "third_party/blink/renderer/core/html/media/media_error.h"
 #include "third_party/blink/renderer/core/html/media/media_fragment_uri_parser.h"
 #include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/core/html/media/media_source_handle.h"
 #include "third_party/blink/renderer/core/html/media/media_source_tracer.h"
 #include "third_party/blink/renderer/core/html/time_ranges.h"
 #include "third_party/blink/renderer/core/html/track/audio_track.h"
@@ -813,7 +814,8 @@
   HTMLElement::InsertedInto(insertion_point);
   if (insertion_point.isConnected()) {
     UseCounter::Count(GetDocument(), WebFeature::kHTMLMediaElementInDocument);
-    if ((!FastGetAttribute(html_names::kSrcAttr).IsEmpty() || src_object_) &&
+    if ((!FastGetAttribute(html_names::kSrcAttr).IsEmpty() ||
+         src_object_stream_descriptor_ || src_object_media_source_handle_) &&
         network_state_ == kNetworkEmpty) {
       ignore_preload_none_ = false;
       InvokeLoadAlgorithm();
@@ -898,12 +900,40 @@
   setAttribute(html_names::kSrcAttr, url);
 }
 
-void HTMLMediaElement::SetSrcObject(MediaStreamDescriptor* src_object) {
-  DVLOG(1) << "setSrcObject(" << *this << ")";
-  src_object_ = src_object;
+void HTMLMediaElement::SetSrcObjectVariant(
+    SrcObjectVariant src_object_variant) {
+  DVLOG(1) << __func__ << "(" << *this << ")";
+  src_object_stream_descriptor_ = nullptr;
+  src_object_media_source_handle_ = nullptr;
+  if (auto** desc = absl::get_if<MediaStreamDescriptor*>(&src_object_variant)) {
+    src_object_stream_descriptor_ = *desc;
+  } else if (auto** handle =
+                 absl::get_if<MediaSourceHandle*>(&src_object_variant)) {
+    src_object_media_source_handle_ = *handle;
+  }
+
+  DVLOG(2) << __func__
+           << ": stream_descriptor=" << src_object_stream_descriptor_
+           << ", media_source_handle=" << src_object_media_source_handle_;
+
   InvokeLoadAlgorithm();
 }
 
+HTMLMediaElement::SrcObjectVariant HTMLMediaElement::GetSrcObjectVariant()
+    const {
+  DVLOG(1) << __func__ << "(" << *this << ")"
+           << ": stream_descriptor=" << src_object_stream_descriptor_
+           << ", media_source_handle=" << src_object_media_source_handle_;
+
+  // At most one is set.
+  DCHECK(!(src_object_stream_descriptor_ && src_object_media_source_handle_));
+
+  if (src_object_media_source_handle_)
+    return SrcObjectVariant(src_object_media_source_handle_.Get());
+
+  return SrcObjectVariant(src_object_stream_descriptor_.Get());
+}
+
 HTMLMediaElement::NetworkState HTMLMediaElement::getNetworkState() const {
   return network_state_;
 }
@@ -1141,7 +1171,7 @@
 
   // 6 - If the media element has an assigned media provider object, then let
   //     mode be object.
-  if (src_object_) {
+  if (src_object_stream_descriptor_ || src_object_media_source_handle_) {
     mode = kObject;
   } else if (FastHasAttribute(html_names::kSrcAttr)) {
     // Otherwise, if the media element has no assigned media provider object
@@ -1209,12 +1239,40 @@
 }
 
 void HTMLMediaElement::LoadSourceFromObject() {
-  DCHECK(src_object_);
+  DCHECK(src_object_stream_descriptor_ || src_object_media_source_handle_);
   load_state_ = kLoadingFromSrcObject;
 
+  if (src_object_media_source_handle_) {
+    DCHECK(!src_object_stream_descriptor_);
+
+    // Retrieve the internal blob URL from the handle that was created in the
+    // context where the referenced MediaSource is owned, for the purposes of
+    // using existing security and logging logic for loading media from a
+    // MediaSource with a blob URL.
+    const String media_source_handle_url_ =
+        src_object_media_source_handle_->GetInternalBlobURL();
+    DCHECK(!media_source_handle_url_.IsEmpty());
+
+    KURL media_url = GetDocument().CompleteURL(media_source_handle_url_);
+    if (!IsSafeToLoadURL(media_url, kComplain)) {
+      MediaLoadingFailed(
+          WebMediaPlayer::kNetworkStateFormatError,
+          BuildElementErrorMessage(
+              "Media load from MediaSourceHandle rejected by safety check"));
+      return;
+    }
+
+    // No type is available when loading from a MediaSourceHandle, via
+    // srcObject, even with an internal MediaSource blob URL.
+    LoadResource(WebMediaPlayerSource(WebURL(media_url)), String());
+    return;
+  }
+
   // No type is available when the resource comes from the 'srcObject'
   // attribute.
-  LoadResource(WebMediaPlayerSource(WebMediaStream(src_object_)), String());
+  LoadResource(
+      WebMediaPlayerSource(WebMediaStream(src_object_stream_descriptor_)),
+      String());
 }
 
 void HTMLMediaElement::LoadSourceFromAttribute() {
@@ -1280,24 +1338,39 @@
   // The resource fetch algorithm
   SetNetworkState(kNetworkLoading);
 
-  // Set current_src_ *before* changing to the cache url, the fact that we are
+  // Set |current_src_| *before* changing to the cache url, the fact that we are
   // loading from the app cache is an internal detail not exposed through the
-  // media element API.
-  current_src_ = url;
+  // media element API. If loading from an internal MediaSourceHandle object
+  // URL, then do not expose that URL to app, but instead hold it for use later
+  // in StartPlayerLoad and elsewhere (for origin, security etc checks normally
+  // done on |current_src_|.)
+  if (src_object_media_source_handle_) {
+    DCHECK(!url.IsEmpty());
+    current_src_.SetSource(url,
+                           SourceMetadata::SourceVisibility::kInvisibleToApp);
+  } else {
+    current_src_.SetSource(url,
+                           SourceMetadata::SourceVisibility::kVisibleToApp);
+  }
 
   // Default this to empty, so that we use |current_src_| unless the player
   // provides one later.
   current_src_after_redirects_ = KURL();
 
   if (audio_source_node_)
-    audio_source_node_->OnCurrentSrcChanged(current_src_);
+    audio_source_node_->OnCurrentSrcChanged(current_src_.GetSourceIfVisible());
 
   // Update remote playback client with the new src and consider it incompatible
   // until proved otherwise.
-  RemotePlaybackCompatibilityChanged(current_src_, false);
+  RemotePlaybackCompatibilityChanged(current_src_.GetSourceIfVisible(), false);
 
-  DVLOG(3) << "loadResource(" << *this << ") - current_src_ -> "
-           << UrlForLoggingMedia(current_src_);
+  DVLOG(3) << "loadResource(" << *this << ") - current src if visible="
+           << UrlForLoggingMedia(current_src_.GetSourceIfVisible())
+           << ", current src =" << UrlForLoggingMedia(current_src_.GetSource())
+           << ", src_object_media_source_handle_="
+           << src_object_media_source_handle_
+           << ", src_object_stream_descriptor_="
+           << src_object_stream_descriptor_;
 
   StartProgressEventTimer();
 
@@ -1309,8 +1382,13 @@
 
   bool attempt_load = true;
 
-  media_source_attachment_ =
-      MediaSourceAttachment::LookupMediaSource(url.GetString());
+  if (src_object_media_source_handle_) {
+    media_source_attachment_ = src_object_media_source_handle_->GetAttachment();
+    DCHECK(media_source_attachment_);
+  } else {
+    media_source_attachment_ =
+        MediaSourceAttachment::LookupMediaSource(url.GetString());
+  }
   if (media_source_attachment_) {
     bool start_result = false;
     media_source_tracer_ =
@@ -1322,9 +1400,12 @@
       // attachment. This can help reduce memory bloat later if the app does not
       // revoke the object URL explicitly and the object URL was the only
       // remaining strong reference to an attached HTMLMediaElement+MediaSource
-      // cycle of objects that could otherwise be garbage-collectable.
+      // cycle of objects that could otherwise be garbage-collectable. Don't
+      // auto-revoke the internal, unregistered, object URL used to attach via
+      // srcObject with a MediaSourceHandle, though.
       if (base::FeatureList::IsEnabled(
-              media::kRevokeMediaSourceObjectURLOnAttach)) {
+              media::kRevokeMediaSourceObjectURLOnAttach) &&
+          !src_object_media_source_handle_) {
         URLFileAPI::revokeObjectURL(GetExecutionContext(), url.GetString());
       }
     } else {
@@ -1370,8 +1451,15 @@
   DCHECK(!web_media_player_);
 
   WebMediaPlayerSource source;
-  if (src_object_) {
-    source = WebMediaPlayerSource(WebMediaStream(src_object_));
+  if (src_object_stream_descriptor_) {
+    source =
+        WebMediaPlayerSource(WebMediaStream(src_object_stream_descriptor_));
+  } else if (src_object_media_source_handle_) {
+    DCHECK(current_src_.GetSourceIfVisible().IsEmpty());
+    const KURL& internal_url = current_src_.GetSource();
+    DCHECK(!internal_url.IsEmpty());
+
+    source = WebMediaPlayerSource(WebURL(internal_url));
   } else {
     // Filter out user:pass as those two URL components aren't
     // considered for media resource fetches (including for the CORS
@@ -1386,7 +1474,7 @@
     // 'authentication flag' to control how user:pass embedded in a
     // media resource URL should be treated, then update the handling
     // here to match.
-    KURL request_url = current_src_;
+    KURL request_url = current_src_.GetSourceIfVisible();
     if (!request_url.User().IsEmpty())
       request_url.SetUser(String());
     if (!request_url.Pass().IsEmpty())
@@ -1545,9 +1633,9 @@
 
 WebMediaPlayer::LoadType HTMLMediaElement::GetLoadType() const {
   if (media_source_attachment_)
-    return WebMediaPlayer::kLoadTypeMediaSource;
+    return WebMediaPlayer::kLoadTypeMediaSource;  // Either via src or srcObject
 
-  if (src_object_)
+  if (src_object_stream_descriptor_)
     return WebMediaPlayer::kLoadTypeMediaStream;
 
   return WebMediaPlayer::kLoadTypeURL;
@@ -1845,7 +1933,9 @@
         MakeGarbageCollected<MediaError>(MediaError::kMediaErrDecode, message));
   } else if ((error == WebMediaPlayer::kNetworkStateFormatError ||
               error == WebMediaPlayer::kNetworkStateNetworkError) &&
-             load_state_ == kLoadingFromSrcAttr) {
+             (load_state_ == kLoadingFromSrcAttr ||
+              (load_state_ == kLoadingFromSrcObject &&
+               src_object_media_source_handle_))) {
     if (message.IsEmpty()) {
       // Generate a more meaningful error message to differentiate the two types
       // of MEDIA_SRC_ERR_NOT_SUPPORTED.
@@ -1959,6 +2049,7 @@
     // skips notification of insecure content. Ensure we always notify the
     // MixedContentChecker of what happened, even if the load was skipped.
     if (LocalFrame* frame = GetDocument().GetFrame()) {
+      const KURL& current_src_for_check = current_src_.GetSource();
       // We don't care about the return value here. The MixedContentChecker will
       // internally notify for insecure content if it needs to regardless of
       // what the return value ends up being for this call.
@@ -1966,13 +2057,13 @@
           frame,
           HasVideo() ? mojom::blink::RequestContextType::VIDEO
                      : mojom::blink::RequestContextType::AUDIO,
-          current_src_,
+          current_src_for_check,
           // Strictly speaking, this check is an approximation; a request could
           // have have redirected back to its original URL, for example.
           // However, the redirect status is only used to prevent leaking
           // information cross-origin via CSP reports, so comparing URLs is
           // sufficient for that purpose.
-          current_src_after_redirects_ == current_src_
+          current_src_after_redirects_ == current_src_for_check
               ? ResourceRequest::RedirectStatus::kNoRedirect
               : ResourceRequest::RedirectStatus::kFollowedRedirect,
           current_src_after_redirects_, /* devtools_id= */ absl::nullopt,
@@ -2022,7 +2113,7 @@
   if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) {
     CreatePlaceholderTracksIfNecessary();
 
-    MediaFragmentURIParser fragment_parser(current_src_);
+    MediaFragmentURIParser fragment_parser(current_src_.GetSource());
     fragment_end_time_ = fragment_parser.EndTime();
 
     // Set the current playback position and the official playback position to
@@ -4304,7 +4395,8 @@
   visitor->Trace(play_promise_resolve_list_);
   visitor->Trace(play_promise_reject_list_);
   visitor->Trace(audio_source_provider_);
-  visitor->Trace(src_object_);
+  visitor->Trace(src_object_stream_descriptor_);
+  visitor->Trace(src_object_media_source_handle_);
   visitor->Trace(autoplay_policy_);
   visitor->Trace(media_controls_);
   visitor->Trace(controls_list_);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h
index 6becfb8..d78ca7c 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element.h
+++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -33,6 +33,7 @@
 #include "base/timer/elapsed_timer.h"
 #include "media/mojo/mojom/media_player.mojom-blink.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/common/media/display_type.h"
 #include "third_party/blink/public/platform/web_media_player_client.h"
 #include "third_party/blink/public/platform/webaudiosourceprovider_impl.h"
@@ -85,6 +86,7 @@
 class HTMLTrackElement;
 class MediaError;
 class MediaSourceAttachment;
+class MediaSourceHandle;
 class MediaSourceTracer;
 class MediaStreamDescriptor;
 class ScriptPromiseResolver;
@@ -177,7 +179,7 @@
 
   // network state
   void SetSrc(const AtomicString&);
-  const KURL& currentSrc() const { return current_src_; }
+  const KURL& currentSrc() const { return current_src_.GetSourceIfVisible(); }
 
   // Return the URL to be used for downloading the media.
   const KURL& downloadURL() const {
@@ -189,8 +191,10 @@
     return current_src_after_redirects_;
   }
 
-  void SetSrcObject(MediaStreamDescriptor*);
-  MediaStreamDescriptor* GetSrcObject() const { return src_object_.Get(); }
+  using SrcObjectVariant =
+      absl::variant<MediaStreamDescriptor*, MediaSourceHandle*>;
+  void SetSrcObjectVariant(SrcObjectVariant src_object_variant);
+  SrcObjectVariant GetSrcObjectVariant() const;
 
   enum NetworkState {
     kNetworkEmpty,
@@ -452,6 +456,30 @@
   friend class PictureInPictureControllerTest;
   friend class VideoWakeLockTest;
 
+  class SourceMetadata {
+    DISALLOW_NEW();
+
+   public:
+    enum class SourceVisibility { kVisibleToApp, kInvisibleToApp };
+    SourceMetadata() = default;
+    void SetSource(const KURL& src, SourceVisibility visibility) {
+      src_ = src;
+      invisible_to_app_ = visibility == SourceVisibility::kInvisibleToApp;
+    }
+    const KURL& GetSourceIfVisible() const {
+      return invisible_to_app_ ? NullURL() : src_;
+    }
+    const KURL& GetSource() const { return src_; }
+
+   private:
+    KURL src_;
+
+    // If true, then |current_src| is used only for internal loading and safety
+    // checks, and for logging that is not visible to apps, either. For example,
+    // when loading from a MediaSourceHandle as srcObject, this would be true.
+    bool invisible_to_app_ = false;
+  };
+
   bool HasPendingActivityInternal() const;
 
   void ResetMediaPlayerAndMediaSource();
@@ -700,9 +728,12 @@
   NetworkState network_state_;
   ReadyState ready_state_;
   ReadyState ready_state_maximum_;
-  KURL current_src_;
+
+  SourceMetadata current_src_;
   KURL current_src_after_redirects_;
-  Member<MediaStreamDescriptor> src_object_;
+
+  Member<MediaStreamDescriptor> src_object_stream_descriptor_;
+  Member<MediaSourceHandle> src_object_media_source_handle_;
 
   // To prevent potential regression when extended by the MSE API, do not set
   // |error_| outside of constructor and SetError().
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
index 57c395de..782bc21 100644
--- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc
+++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -296,7 +296,8 @@
   HTMLMediaElement* Media() const { return media_.Get(); }
   void SetCurrentSrc(const AtomicString& src) {
     KURL url(src);
-    Media()->current_src_ = url;
+    Media()->current_src_.SetSource(
+        url, HTMLMediaElement::SourceMetadata::SourceVisibility::kVisibleToApp);
   }
 
   MockWebMediaPlayer* MockMediaPlayer() { return media_player_; }
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.cc b/third_party/blink/renderer/core/layout/hit_test_result.cc
index c08f010a..958be189 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.cc
+++ b/third_party/blink/renderer/core/layout/hit_test_result.cc
@@ -22,6 +22,7 @@
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 
 #include "cc/base/region.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
 #include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
 #include "third_party/blink/renderer/core/dom/pseudo_element.h"
@@ -39,6 +40,7 @@
 #include "third_party/blink/renderer/core/html/html_image_element.h"
 #include "third_party/blink/renderer/core/html/html_map_element.h"
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
+#include "third_party/blink/renderer/core/html/media/media_source_handle.h"
 #include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/input_type_names.h"
@@ -440,8 +442,26 @@
 }
 
 MediaStreamDescriptor* HitTestResult::GetMediaStreamDescriptor() const {
-  if (HTMLMediaElement* media_elt = MediaElement())
-    return media_elt->GetSrcObject();
+  if (HTMLMediaElement* media_elt = MediaElement()) {
+    auto variant = media_elt->GetSrcObjectVariant();
+    if (absl::holds_alternative<MediaStreamDescriptor*>(variant)) {
+      // It might be nullptr-valued variant, too, here, but we return nullptr
+      // for that, regardless.
+      return absl::get<MediaStreamDescriptor*>(variant);
+    }
+  }
+  return nullptr;
+}
+
+MediaSourceHandle* HitTestResult::GetMediaSourceHandle() const {
+  if (HTMLMediaElement* media_elt = MediaElement()) {
+    auto variant = media_elt->GetSrcObjectVariant();
+    if (absl::holds_alternative<MediaSourceHandle*>(variant)) {
+      // It might be a nullptr-valued MediaStreamDescriptor* variant, here, but
+      // we return nullptr for that, regardless.
+      return absl::get<MediaSourceHandle*>(variant);
+    }
+  }
   return nullptr;
 }
 
diff --git a/third_party/blink/renderer/core/layout/hit_test_result.h b/third_party/blink/renderer/core/layout/hit_test_result.h
index 5105121..37e272f 100644
--- a/third_party/blink/renderer/core/layout/hit_test_result.h
+++ b/third_party/blink/renderer/core/layout/hit_test_result.h
@@ -51,6 +51,7 @@
 class HTMLMediaElement;
 class Image;
 class KURL;
+class MediaSourceHandle;
 class MediaStreamDescriptor;
 class NGPhysicalBoxFragment;
 class Node;
@@ -161,6 +162,7 @@
   KURL AbsoluteImageURL() const;
   KURL AbsoluteMediaURL() const;
   MediaStreamDescriptor* GetMediaStreamDescriptor() const;
+  MediaSourceHandle* GetMediaSourceHandle() const;
   KURL AbsoluteLinkURL() const;
   String TextContent() const;
   bool IsLiveLink() const;
diff --git a/third_party/blink/renderer/core/page/context_menu_controller.cc b/third_party/blink/renderer/core/page/context_menu_controller.cc
index 612d9ede..e8022633 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller.cc
@@ -484,12 +484,13 @@
     data.alt_text = html_element->AltText().Utf8();
   }
   if (!result.AbsoluteMediaURL().IsEmpty() ||
-      result.GetMediaStreamDescriptor()) {
+      result.GetMediaStreamDescriptor() || result.GetMediaSourceHandle()) {
     if (!result.AbsoluteMediaURL().IsEmpty())
       data.src_url = GURL(result.AbsoluteMediaURL());
 
     // We know that if absoluteMediaURL() is not empty or element has a media
-    // stream descriptor, then this is a media element.
+    // stream descriptor or element has a media source handle, then this is a
+    // media element.
     auto* media_element = To<HTMLMediaElement>(result.InnerNode());
     if (IsA<HTMLVideoElement>(*media_element)) {
       // A video element should be presented as an audio element when it has an
diff --git a/third_party/blink/renderer/core/page/context_menu_controller_test.cc b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
index b8d1e74..2929d090 100644
--- a/third_party/blink/renderer/core/page/context_menu_controller_test.cc
+++ b/third_party/blink/renderer/core/page/context_menu_controller_test.cc
@@ -413,7 +413,7 @@
   MediaStreamComponentVector dummy_components;
   auto* media_stream_descriptor = MakeGarbageCollected<MediaStreamDescriptor>(
       dummy_components, dummy_components);
-  video->SetSrcObject(media_stream_descriptor);
+  video->SetSrcObjectVariant(media_stream_descriptor);
   GetDocument()->body()->AppendChild(video);
   test::RunPendingTasks();
   SetReadyState(video.Get(), HTMLMediaElement::kHaveMetadata);
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 36e9e17..e212606 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -3130,8 +3130,15 @@
     PaintPropertyTreeBuilderFragmentContext& context) {
   DCHECK(!IsInNGFragmentTraversal());
   InitFragmentPaintProperties(fragment, needs_paint_properties, context);
-  fragment.SetLegacyPaginationOffset(pagination_offset);
-  fragment.SetLogicalTopInFlowThread(context.logical_top_in_flow_thread);
+  if (context.current.fragmentainer_idx == WTF::kNotFound) {
+    fragment.SetLegacyPaginationOffset(pagination_offset);
+    fragment.SetLogicalTopInFlowThread(context.logical_top_in_flow_thread);
+  } else {
+    // We're inside (monolithic) legacy content, but further out there's an NG
+    // fragmentation context. Use the fragmentainer index, just like we do for
+    // NG objects.
+    fragment.SetFragmentID(context.current.fragmentainer_idx);
+  }
 }
 
 void PaintPropertyTreeBuilder::InitFragmentPaintPropertiesForNG(
@@ -3140,6 +3147,8 @@
     context_.fragments.push_back(PaintPropertyTreeBuilderFragmentContext());
   else
     context_.fragments.resize(1);
+  context_.fragments[0].current.fragmentainer_idx =
+      pre_paint_info_->fragmentainer_idx;
   InitFragmentPaintProperties(*pre_paint_info_->fragment_data,
                               needs_paint_properties, context_.fragments[0]);
 }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
index 0948140..e713267 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -118,6 +118,14 @@
     // that are baked in PaintOffsetTranslations since we entered the
     // fragmentainer.
     PhysicalOffset paint_offset_for_oof_in_fragmentainer;
+
+    // The fragmentainer index of the nearest ancestor that participates in
+    // block fragmentation. This is updated as we update properties for an
+    // object that participates in block fragmentation. If we enter monolithic
+    // content (legacy or NG), the index will be kept and inherited down the
+    // tree, so that we eventually set the correct "NG" fragment index in the
+    // FragmentData object, rather than using a bogus legacy flow-thread offset.
+    wtf_size_t fragmentainer_idx = WTF::kNotFound;
   };
 
   ContainingBlockContext current;
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc
index 2059ed0..1699485 100644
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_sink.cc
@@ -225,14 +225,14 @@
       &MediaStreamVideoTrackUnderlyingSink::ConvertDone, WrapPersistent(this),
       resolver, video_frame, estimated_capture_time);
   const bool success = accelerated_frame_pool_->ConvertVideoFrame(
-      std::move(video_frame), gfx::ColorSpace::CreateREC709(),
+      video_frame, gfx::ColorSpace::CreateREC709(),
       std::move(convert_done_callback));
   if (success) {
     convert_to_nv12_gmb_failure_count_ = 0;
   } else {
+    ConvertDone(resolver, video_frame, estimated_capture_time,
+                /*converted_video_frame=*/nullptr);
     convert_to_nv12_gmb_failure_count_++;
-    // Note that `ConvertVideoFrame` will call `convert_done_callback` with
-    // nullptr even if it returns false, so we still return resolver->Promise()
   }
   return resolver->Promise();
 }
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
index fc28f85..f119c1f 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/run_loop.h"
 #include "base/test/gmock_callback_support.h"
 #include "media/base/limits.h"
+#include "media/base/video_util.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
@@ -112,6 +113,21 @@
       scoped_refptr<media::VideoFrame> video_frame,
       std::vector<scoped_refptr<media::VideoFrame>> scaled_video_frames,
       base::TimeTicks estimated_capture_time) {
+    if (video_frame->format() != media::PIXEL_FORMAT_I420 &&
+        video_frame->format() != media::PIXEL_FORMAT_I420A) {
+      auto size = video_frame->visible_rect().size();
+      auto converted_format =
+          opaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A;
+      auto i420_frame = media::VideoFrame::CreateFrame(
+          converted_format, size, gfx::Rect(size), size,
+          video_frame->timestamp());
+      std::vector<uint8_t> tmp_buf;
+      auto status =
+          media::ConvertAndScaleFrame(*video_frame, *i420_frame, tmp_buf);
+      EXPECT_TRUE(status.is_ok());
+      video_frame = i420_frame;
+    }
+
     if (opaque)
       EXPECT_EQ(media::PIXEL_FORMAT_I420, video_frame->format());
     else
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
index aab5622..18166536 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.h"
 
 #include "base/memory/ptr_util.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 #include "third_party/blink/public/mojom/mediastream/media_devices.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -181,7 +182,11 @@
           track->Component(),
           MediaStreamDescriptorClient::DispatchEventTiming::kScheduled);
     }
-    MediaStreamDescriptor* const descriptor = media_element_->GetSrcObject();
+    auto variant = media_element_->GetSrcObjectVariant();
+    // The load type check above, should prevent this from failing:
+    DCHECK(absl::holds_alternative<MediaStreamDescriptor*>(variant));
+    MediaStreamDescriptor* const descriptor =
+        absl::get<MediaStreamDescriptor*>(variant);
     DCHECK(descriptor);
     for (unsigned i = 0; i < descriptor->NumberOfAudioComponents(); i++) {
       media_stream_->AddTrackByComponentAndFireEvents(
@@ -311,7 +316,11 @@
 
   // If |element| is actually playing a MediaStream, just clone it.
   if (element.GetLoadType() == WebMediaPlayer::kLoadTypeMediaStream) {
-    MediaStreamDescriptor* const element_descriptor = element.GetSrcObject();
+    auto variant = element.GetSrcObjectVariant();
+    // The load type check above, should prevent this from failing:
+    DCHECK(absl::holds_alternative<MediaStreamDescriptor*>(variant));
+    MediaStreamDescriptor* const element_descriptor =
+        absl::get<MediaStreamDescriptor*>(variant);
     DCHECK(element_descriptor);
     return MediaStream::Create(context, element_descriptor);
   }
diff --git a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
index a0f51b3..54fab7b 100644
--- a/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/h264_encoder.cc
@@ -115,7 +115,8 @@
   TRACE_EVENT0("media", "H264Encoder::EncodeOnEncodingTaskRunner");
   DCHECK(encoding_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_NV12 ||
-         frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420);
+         frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420 ||
+         frame->format() == media::VideoPixelFormat::PIXEL_FORMAT_I420A);
 
   if (frame->format() == media::PIXEL_FORMAT_NV12)
     frame = ConvertToI420ForSoftwareEncoder(frame);
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
index d7aa5c58..9dc5103 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_test.cc
@@ -227,7 +227,7 @@
       MediaStreamComponentVector dummy_tracks;
       auto* descriptor = MakeGarbageCollected<MediaStreamDescriptor>(
           dummy_tracks, dummy_tracks);
-      Video()->SetSrcObject(descriptor);
+      Video()->SetSrcObjectVariant(descriptor);
     } else {
       Video()->SetSrc("http://example.com/foo.mp4");
     }
diff --git a/third_party/blink/renderer/modules/srcobject/BUILD.gn b/third_party/blink/renderer/modules/srcobject/BUILD.gn
index e70b0e5a..13afbba 100644
--- a/third_party/blink/renderer/modules/srcobject/BUILD.gn
+++ b/third_party/blink/renderer/modules/srcobject/BUILD.gn
@@ -9,5 +9,8 @@
     "html_media_element_src_object.cc",
     "html_media_element_src_object.h",
   ]
-  deps = [ "//third_party/blink/renderer/modules/mediastream" ]
+  deps = [
+    "//third_party/blink/renderer/modules/mediasource",
+    "//third_party/blink/renderer/modules/mediastream",
+  ]
 }
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc
index 2409a44..adf49d9 100644
--- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc
+++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.cc
@@ -4,18 +4,35 @@
 
 #include "third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h"
 
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_mediasourcehandle_mediastream.h"
 #include "third_party/blink/renderer/core/html/media/html_media_element.h"
+#include "third_party/blink/renderer/core/html/media/media_source_handle.h"
+#include "third_party/blink/renderer/modules/mediasource/media_source_handle_impl.h"
 #include "third_party/blink/renderer/modules/mediastream/media_stream.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
 
 namespace blink {
 
 // static
-MediaStream* HTMLMediaElementSrcObject::srcObject(HTMLMediaElement& element) {
-  MediaStreamDescriptor* descriptor = element.GetSrcObject();
+V8MediaProvider* HTMLMediaElementSrcObject::srcObject(
+    HTMLMediaElement& element) {
+  HTMLMediaElement::SrcObjectVariant src_object_variant =
+      element.GetSrcObjectVariant();
+
+  if (absl::holds_alternative<blink::MediaSourceHandle*>(src_object_variant)) {
+    auto* handle = absl::get<MediaSourceHandle*>(src_object_variant);
+    DCHECK(handle);  // A nullptr is seen as a MediaStreamDescriptor*.
+    return MakeGarbageCollected<V8MediaProvider>(
+        static_cast<MediaSourceHandleImpl*>(handle));
+  }
+
+  // Otherwise, it is either null or a non-nullptr MediaStreamDescriptor*.
+  auto* descriptor = absl::get<MediaStreamDescriptor*>(src_object_variant);
   if (descriptor) {
     MediaStream* stream = ToMediaStream(descriptor);
-    return stream;
+    return MakeGarbageCollected<V8MediaProvider>(stream);
   }
 
   return nullptr;
@@ -23,12 +40,36 @@
 
 // static
 void HTMLMediaElementSrcObject::setSrcObject(HTMLMediaElement& element,
-                                             MediaStream* media_stream) {
-  if (!media_stream) {
-    element.SetSrcObject(nullptr);
+                                             V8MediaProvider* media_provider) {
+  if (!media_provider) {
+    // Default-constructed variant is a nullptr-valued MediaStreamDescriptor*
+    // since that type is the 0'th index of an
+    // HTMLMediaElement::SrcObjectVariant.
+    element.SetSrcObjectVariant(HTMLMediaElement::SrcObjectVariant());
     return;
   }
-  element.SetSrcObject(media_stream->Descriptor());
+
+  switch (media_provider->GetContentType()) {
+    case V8MediaProvider::ContentType::kMediaSourceHandle: {
+      MediaSourceHandle* handle = media_provider->GetAsMediaSourceHandle();
+
+      // JS null MediaProvider is a nullptr in |media_provider|, handled above.
+      DCHECK(handle);
+
+      handle->mark_used();
+      element.SetSrcObjectVariant(handle);
+      break;
+    }
+    case V8MediaProvider::ContentType::kMediaStream: {
+      MediaStream* media_stream = media_provider->GetAsMediaStream();
+
+      // JS null MediaProvider is a nullptr in |media_provider|, handled above.
+      DCHECK(media_stream);
+
+      element.SetSrcObjectVariant(media_stream->Descriptor());
+      break;
+    }
+  }
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h
index f3ca4f9..d48a7cd 100644
--- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h
+++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.h
@@ -5,20 +5,20 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_SRCOBJECT_HTML_MEDIA_ELEMENT_SRC_OBJECT_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_SRCOBJECT_HTML_MEDIA_ELEMENT_SRC_OBJECT_H_
 
+#include "third_party/blink/renderer/bindings/modules/v8/v8_typedefs.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 namespace blink {
 
-class MediaStream;
 class HTMLMediaElement;
 
 class MODULES_EXPORT HTMLMediaElementSrcObject {
   STATIC_ONLY(HTMLMediaElementSrcObject);
 
  public:
-  static MediaStream* srcObject(HTMLMediaElement&);
-  static void setSrcObject(HTMLMediaElement&, MediaStream*);
+  static V8MediaProvider* srcObject(HTMLMediaElement&);
+  static void setSrcObject(HTMLMediaElement&, V8MediaProvider*);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl
index 0481d3b3..f6f2b88c 100644
--- a/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl
+++ b/third_party/blink/renderer/modules/srcobject/html_media_element_src_object.idl
@@ -5,7 +5,7 @@
 // https://html.spec.whatwg.org/C/#dom-media-srcobject
 
 // TODO(guidou): Add support for MediaSource and Blob, as defined in the spec.
-typedef MediaStream MediaProvider;
+typedef (MediaSourceHandle or MediaStream) MediaProvider;
 
 [
     ImplementedAs=HTMLMediaElementSrcObject
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 585419a..96905ade 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1771,24 +1771,25 @@
   return true;
 }
 
-void WebGLRenderingContextBase::CopyRenderingResultsToVideoFrame(
+bool WebGLRenderingContextBase::CopyRenderingResultsToVideoFrame(
     WebGraphicsContext3DVideoFramePool* frame_pool,
     SourceDrawingBuffer src_buffer,
     const gfx::ColorSpace& dst_color_space,
-    VideoFrameCopyCompletedCallback& callback) {
+    VideoFrameCopyCompletedCallback callback) {
   if (!frame_pool)
-    return;
+    return false;
 
   auto* drawing_buffer = GetDrawingBuffer();
   if (!drawing_buffer)
-    return;
+    return false;
 
   ScopedFramebufferRestorer fbo_restorer(this);
   if (!drawing_buffer->ResolveAndBindForReadAndDraw())
-    return;
+    return false;
 
-  drawing_buffer->CopyToVideoFrame(frame_pool, src_buffer, is_origin_top_left_,
-                                   dst_color_space, callback);
+  return drawing_buffer->CopyToVideoFrame(frame_pool, src_buffer,
+                                          is_origin_top_left_, dst_color_space,
+                                          std::move(callback));
 }
 
 gfx::Size WebGLRenderingContextBase::DrawingBufferSize() const {
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index bc1235e..78feed5 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -724,11 +724,11 @@
   bool PaintRenderingResultsToCanvas(SourceDrawingBuffer) override;
   bool CopyRenderingResultsFromDrawingBuffer(CanvasResourceProvider*,
                                              SourceDrawingBuffer) override;
-  void CopyRenderingResultsToVideoFrame(
+  bool CopyRenderingResultsToVideoFrame(
       WebGraphicsContext3DVideoFramePool*,
       SourceDrawingBuffer,
       const gfx::ColorSpace&,
-      VideoFrameCopyCompletedCallback&) override;
+      VideoFrameCopyCompletedCallback) override;
 
   cc::Layer* CcLayer() const override;
   void Stop() override;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index ccc5638..100db37 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1071,7 +1071,7 @@
   // Use an empty sync token for `mailbox_holder` because we have already waited
   // on the required sync tokens above.
   gpu::MailboxHolder mailbox_holder(mailbox, gpu::SyncToken(), texture_target_);
-  copy_function(mailbox_holder, format, size, color_space);
+  bool succeeded = copy_function(mailbox_holder, format, size, color_space);
 
   gpu::SyncToken sync_token;
   dst_interface->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
@@ -1081,7 +1081,7 @@
         texture_id_to_restore_access,
         GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
   }
-  return true;
+  return succeeded;
 }
 
 bool DrawingBuffer::CopyToPlatformTexture(gpu::gles2::GLES2Interface* dst_gl,
@@ -1105,7 +1105,7 @@
 
   auto copy_function = [&](const gpu::MailboxHolder& src_mailbox,
                            viz::ResourceFormat, const gfx::Size&,
-                           const gfx::ColorSpace&) {
+                           const gfx::ColorSpace&) -> bool {
     GLuint src_texture = dst_gl->CreateAndTexStorage2DSharedImageCHROMIUM(
         src_mailbox.mailbox.name);
     dst_gl->BeginSharedImageAccessDirectCHROMIUM(
@@ -1118,6 +1118,7 @@
         unpack_unpremultiply_alpha_needed);
     dst_gl->EndSharedImageAccessDirectCHROMIUM(src_texture);
     dst_gl->DeleteTextures(1, &src_texture);
+    return true;
   };
   return CopyToPlatformInternal(dst_gl, src_buffer, copy_function);
 }
@@ -1136,61 +1137,41 @@
 
   auto copy_function = [&](const gpu::MailboxHolder& src_mailbox,
                            viz::ResourceFormat, const gfx::Size&,
-                           const gfx::ColorSpace&) {
+                           const gfx::ColorSpace&) -> bool {
     dst_raster_interface->CopySubTexture(
         src_mailbox.mailbox, dst_mailbox, dst_texture_target,
         dst_texture_offset.x(), dst_texture_offset.y(), src_sub_rectangle.x(),
         src_sub_rectangle.y(), src_sub_rectangle.width(),
         src_sub_rectangle.height(), flip_y, unpack_premultiply_alpha_needed);
+    return true;
   };
 
   return CopyToPlatformInternal(dst_raster_interface, src_buffer,
                                 copy_function);
 }
 
-void DrawingBuffer::CopyToVideoFrame(
+bool DrawingBuffer::CopyToVideoFrame(
     WebGraphicsContext3DVideoFramePool* frame_pool,
     SourceDrawingBuffer src_buffer,
     bool src_origin_is_top_left,
     const gfx::ColorSpace& dst_color_space,
-    WebGraphicsContext3DVideoFramePool::FrameReadyCallback& callback) {
-  const GrSurfaceOrigin src_surface_origin = src_origin_is_top_left
-                                                 ? kTopLeft_GrSurfaceOrigin
-                                                 : kBottomLeft_GrSurfaceOrigin;
-  // Split the callback so that one can be consumed by the copy if it succeeds,
-  // and the other can be used to restore the original callback reference.
-  auto split_callback = base::SplitOnceCallback(std::move(callback));
-  // Restore the original callback; we will reset it below if the copy succeeds.
-  callback = std::move(split_callback.first);
-
-  // Frame pool copy callback that wraps the original (split) callback.
-  auto frame_pool_callback = base::BindOnce(
-      [](WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback,
-         scoped_refptr<media::VideoFrame> video_frame) {
-        // Only run callback if copy succeeds, otherwise caller will handle
-        // failure e.g. HTMLCanvasElement fallback to static bitmap image copy.
-        if (video_frame)
-          std::move(callback).Run(std::move(video_frame));
-      },
-      std::move(split_callback.second));
-
-  auto copy_function =
-      [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat src_format,
-          const gfx::Size& src_size, const gfx::ColorSpace& src_color_space) {
-        if (frame_pool->CopyRGBATextureToVideoFrame(
-                src_format, src_size, src_color_space, src_surface_origin,
-                src_mailbox, dst_color_space, std::move(frame_pool_callback))) {
-          // This method indicates success by consuming the callback argument
-          // so do that if the copy has consumed the wrapped split callback.
-          callback.Reset();
-        }
-      };
+    WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback) {
   // Ensure that `frame_pool` has not experienced a context loss.
   // https://crbug.com/1269230
   auto* raster_interface = frame_pool->GetRasterInterface();
   if (!raster_interface)
-    return;
-  CopyToPlatformInternal(raster_interface, src_buffer, copy_function);
+    return false;
+  const GrSurfaceOrigin src_surface_origin = src_origin_is_top_left
+                                                 ? kTopLeft_GrSurfaceOrigin
+                                                 : kBottomLeft_GrSurfaceOrigin;
+  auto copy_function =
+      [&](const gpu::MailboxHolder& src_mailbox, viz::ResourceFormat src_format,
+          const gfx::Size& src_size, const gfx::ColorSpace& src_color_space) {
+        return frame_pool->CopyRGBATextureToVideoFrame(
+            src_format, src_size, src_color_space, src_surface_origin,
+            src_mailbox, dst_color_space, std::move(callback));
+      };
+  return CopyToPlatformInternal(raster_interface, src_buffer, copy_function);
 }
 
 cc::Layer* DrawingBuffer::CcLayer() {
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index 25773d4..2648412 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -284,12 +284,12 @@
                              const gfx::Rect& src_sub_rectangle,
                              SourceDrawingBuffer src_buffer);
 
-  void CopyToVideoFrame(
+  bool CopyToVideoFrame(
       WebGraphicsContext3DVideoFramePool* frame_pool,
       SourceDrawingBuffer src_buffer,
       bool src_origin_is_top_left,
       const gfx::ColorSpace& dst_color_space,
-      WebGraphicsContext3DVideoFramePool::FrameReadyCallback& callback);
+      WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback);
 
   sk_sp<SkData> PaintRenderingResultsToDataArray(SourceDrawingBuffer);
 
@@ -459,8 +459,8 @@
     gpu::SyncToken receive_sync_token;
   };
 
-  // CopyFunction(const gpu::MailboxHolder&, viz::ResourceFormat,
-  //              const gfx::Size&, const gfx::ColorSpace&)
+  // bool CopyFunction(const gpu::MailboxHolder&, viz::ResourceFormat,
+  //                   const gfx::Size&, const gfx::ColorSpace&)
   template <typename CopyFunction>
   bool CopyToPlatformInternal(gpu::InterfaceBase* dst_interface,
                               SourceDrawingBuffer src_buffer,
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc
index 2355f36..0592eea 100644
--- a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc
+++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.cc
@@ -66,9 +66,7 @@
           std::move(sk_image), gfx::Rect(sk_image_size), sk_image_size,
           base::TimeDelta());
       if (sk_image_video_frame) {
-        std::move(callback).Run(
-            ConvertToYUVFrame(std::move(sk_image_video_frame),
-                              /* flip = */ false));
+        std::move(callback).Run(std::move(sk_image_video_frame));
         return;
       }
     }
@@ -86,6 +84,8 @@
 
   // Try async reading if image is texture backed.
   if (image->CurrentFrameKnownToBeOpaque() || can_discard_alpha_) {
+    // Split the callback so it can be used for both the GMB frame pool copy and
+    // ReadYUVPixelsAsync fallback paths.
     auto split_callback = base::SplitOnceCallback(std::move(callback));
     if (accelerated_frame_pool_enabled_) {
       if (!accelerated_frame_pool_) {
@@ -93,44 +93,21 @@
             std::make_unique<WebGraphicsContext3DVideoFramePool>(
                 context_provider);
       }
-      auto blit_done_lambda =
-          [](base::WeakPtr<StaticBitmapImageToVideoFrameCopier> converter,
-             base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper>
-                 context_provider,
-             scoped_refptr<StaticBitmapImage> image,
-             FrameReadyCallback callback,
-             scoped_refptr<media::VideoFrame> video_frame) {
-            if (!converter)
-              return;
-            if (video_frame) {
-              converter->OnYUVPixelsReadAsync(video_frame, std::move(callback),
-                                              true);
-            } else if (context_provider) {
-              converter->ReadYUVPixelsAsync(image,
-                                            context_provider->ContextProvider(),
-                                            std::move(callback));
-            }
-          };
-      auto blit_done_callback =
-          WTF::Bind(blit_done_lambda, weak_ptr_factory_.GetWeakPtr(),
-                    context_provider, image, std::move(split_callback.first));
-
       // TODO(https://crbug.com/1224279): This assumes that all
       // StaticBitmapImages are 8-bit sRGB. Expose the color space and pixel
       // format that is backing `image->GetMailboxHolder()`, or, alternatively,
       // expose an accelerated SkImage.
-      accelerated_frame_pool_->CopyRGBATextureToVideoFrame(
-          viz::SkColorTypeToResourceFormat(kRGBA_8888_SkColorType),
-          gfx::Size(image->width(), image->height()),
-          gfx::ColorSpace::CreateSRGB(),
-          image->IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
-                                   : kBottomLeft_GrSurfaceOrigin,
-          image->GetMailboxHolder(), gfx::ColorSpace::CreateREC709(),
-          std::move(blit_done_callback));
-      // Early out even if the above fails since it would've already invoked the
-      // FrameReadyCallback with a null VideoFrame to indicate failure, and that
-      // will cause us to the take the fallback path in |blit_done_lambda|.
-      return;
+      if (accelerated_frame_pool_->CopyRGBATextureToVideoFrame(
+              viz::SkColorTypeToResourceFormat(kRGBA_8888_SkColorType),
+              gfx::Size(image->width(), image->height()),
+              gfx::ColorSpace::CreateSRGB(),
+              image->IsOriginTopLeft() ? kTopLeft_GrSurfaceOrigin
+                                       : kBottomLeft_GrSurfaceOrigin,
+              image->GetMailboxHolder(), gfx::ColorSpace::CreateREC709(),
+              std::move(split_callback.first))) {
+        // Early out on success, otherwise fallback to ReadYUVPixelsAsync path.
+        return;
+      }
     }
     ReadYUVPixelsAsync(image, context_provider->ContextProvider(),
                        std::move(split_callback.second));
@@ -168,8 +145,7 @@
     DLOG(ERROR) << "Couldn't read pixels from PaintImage";
     return;
   }
-  std::move(callback).Run(
-      ConvertToYUVFrame(std::move(temp_argb_frame), /* flip = */ false));
+  std::move(callback).Run(std::move(temp_argb_frame));
 }
 
 void StaticBitmapImageToVideoFrameCopier::ReadARGBPixelsAsync(
@@ -272,8 +248,51 @@
     return;
   }
 
-  bool flip = result_origin == kBottomLeft_GrSurfaceOrigin;
-  std::move(callback).Run(ConvertToYUVFrame(std::move(temp_argb_frame), flip));
+  // If a frame comes with BottomLeft origin it's effectively upside down.
+  // Frame consumers are not ready to deal with it. We can swap rows to fix it,
+  // but it would add an extra copy. Instead we set up a wrapper frame that
+  // references the same data but has color planes with negative strides,
+  // it forces all the code that handles frames to process rows bottom-up.
+  auto& coded_size = temp_argb_frame->coded_size();
+  if (result_origin == kBottomLeft_GrSurfaceOrigin && coded_size.height() > 1) {
+    auto pixel_format = temp_argb_frame->format();
+    auto rgb_plane = temp_argb_frame->layout().planes()[0];
+    size_t last_row_offset =
+        rgb_plane.offset + rgb_plane.stride * (coded_size.height() - 1);
+    media::ColorPlaneLayout reverse_rgb_plane(-rgb_plane.stride,
+                                              last_row_offset, rgb_plane.size);
+
+    std::vector<media::ColorPlaneLayout> planes{reverse_rgb_plane};
+    if (temp_argb_frame->layout().planes().size() > 1 && !can_discard_alpha_) {
+      auto alpha_plane = temp_argb_frame->layout().planes()[1];
+      last_row_offset =
+          alpha_plane.offset + alpha_plane.stride * (coded_size.height() - 1);
+      media::ColorPlaneLayout reverse_alpha_plane(
+          -alpha_plane.stride, last_row_offset, alpha_plane.size);
+      planes.push_back(reverse_alpha_plane);
+    } else {
+      // Dropping alpha from pixel format
+      if (pixel_format == media::PIXEL_FORMAT_ARGB)
+        pixel_format = media::PIXEL_FORMAT_XRGB;
+      else if (pixel_format == media::PIXEL_FORMAT_ABGR)
+        pixel_format = media::PIXEL_FORMAT_XBGR;
+    }
+    auto layout = media::VideoFrameLayout::CreateWithPlanes(pixel_format,
+                                                            coded_size, planes)
+                      .value();
+
+    const auto& last_plane = layout.planes()[layout.planes().size() - 1];
+    size_t data_size = last_plane.offset + last_plane.size;
+    auto reverse_stride_frame = media::VideoFrame::WrapExternalDataWithLayout(
+        layout, gfx::Rect(coded_size), coded_size,
+        temp_argb_frame->data(media::VideoFrame::kARGBPlane), data_size,
+        temp_argb_frame->timestamp());
+
+    reverse_stride_frame->AddDestructionObserver(base::BindOnce(
+        [](scoped_refptr<media::VideoFrame>) {}, std::move(temp_argb_frame)));
+    temp_argb_frame = reverse_stride_frame;
+  }
+  std::move(callback).Run(std::move(temp_argb_frame));
 }
 
 void StaticBitmapImageToVideoFrameCopier::OnYUVPixelsReadAsync(
@@ -295,70 +314,4 @@
   image = nullptr;
 }
 
-scoped_refptr<media::VideoFrame>
-StaticBitmapImageToVideoFrameCopier::ConvertToYUVFrame(
-    scoped_refptr<media::VideoFrame> temp_argb_frame,
-    bool flip) {
-  DVLOG(4) << __func__;
-  DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
-  TRACE_EVENT0("webrtc", "CanvasCaptureHandler::ConvertToYUVFrame");
-
-  const bool skip_alpha =
-      media::IsOpaque(temp_argb_frame->format()) || can_discard_alpha_;
-  const uint8_t* source_ptr =
-      temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane);
-  const gfx::Size image_size = temp_argb_frame->coded_size();
-  const int stride = temp_argb_frame->stride(media::VideoFrame::kARGBPlane);
-
-  scoped_refptr<media::VideoFrame> video_frame = frame_pool_.CreateFrame(
-      skip_alpha ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
-      image_size, gfx::Rect(image_size), image_size, base::TimeDelta());
-  if (!video_frame) {
-    DLOG(ERROR) << "Couldn't allocate video frame";
-    return nullptr;
-  }
-
-  int (*ConvertToI420)(const uint8_t* src_argb, int src_stride_argb,
-                       uint8_t* dst_y, int dst_stride_y, uint8_t* dst_u,
-                       int dst_stride_u, uint8_t* dst_v, int dst_stride_v,
-                       int width, int height) = nullptr;
-  switch (temp_argb_frame->format()) {
-    case media::PIXEL_FORMAT_XBGR:
-    case media::PIXEL_FORMAT_ABGR:
-      ConvertToI420 = libyuv::ABGRToI420;
-      break;
-    case media::PIXEL_FORMAT_XRGB:
-    case media::PIXEL_FORMAT_ARGB:
-      ConvertToI420 = libyuv::ARGBToI420;
-      break;
-    default:
-      NOTIMPLEMENTED() << "Unexpected pixel format.";
-      return nullptr;
-  }
-
-  if (ConvertToI420(source_ptr, stride,
-                    video_frame->visible_data(media::VideoFrame::kYPlane),
-                    video_frame->stride(media::VideoFrame::kYPlane),
-                    video_frame->visible_data(media::VideoFrame::kUPlane),
-                    video_frame->stride(media::VideoFrame::kUPlane),
-                    video_frame->visible_data(media::VideoFrame::kVPlane),
-                    video_frame->stride(media::VideoFrame::kVPlane),
-                    image_size.width(),
-                    (flip ? -1 : 1) * image_size.height()) != 0) {
-    DLOG(ERROR) << "Couldn't convert to I420";
-    return nullptr;
-  }
-  if (!skip_alpha) {
-    // It is ok to use ARGB function because alpha has the same alignment for
-    // both ABGR and ARGB.
-    libyuv::ARGBExtractAlpha(
-        source_ptr, stride,
-        video_frame->visible_data(media::VideoFrame::kAPlane),
-        video_frame->stride(media::VideoFrame::kAPlane), image_size.width(),
-        (flip ? -1 : 1) * image_size.height());
-  }
-
-  return video_frame;
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h
index 83fc1f0..a1a11cbc 100644
--- a/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h
+++ b/third_party/blink/renderer/platform/graphics/static_bitmap_image_to_video_frame_copier.h
@@ -65,10 +65,6 @@
                             bool success);
   void OnReleaseMailbox(scoped_refptr<StaticBitmapImage> image);
 
-  scoped_refptr<media::VideoFrame> ConvertToYUVFrame(
-      scoped_refptr<media::VideoFrame> argb_video_frame,
-      bool flip);
-
   media::VideoFramePool frame_pool_;
   std::unique_ptr<WebGraphicsContext3DVideoFramePool> accelerated_frame_pool_;
   bool can_discard_alpha_ = false;
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
index 0a54857..ee2c57b0 100644
--- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
+++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -120,11 +120,6 @@
     const gpu::MailboxHolder& src_mailbox_holder,
     const gfx::ColorSpace& dst_color_space,
     FrameReadyCallback callback) {
-  // Issue `callback` with a nullptr VideoFrame if we return early.
-  base::ScopedClosureRunner failure_runner(WTF::Bind(
-      [](FrameReadyCallback* callback) { std::move(*callback).Run(nullptr); },
-      base::Unretained(&callback)));
-
   if (!weak_context_provider_)
     return false;
   auto* context_provider = weak_context_provider_->ContextProvider();
@@ -154,10 +149,15 @@
   const bool copy_succeeded = media::CopyRGBATextureToVideoFrame(
       raster_context_provider, src_format, src_size, src_color_space,
       src_surface_origin, src_mailbox_holder, dst_frame.get());
-  if (!copy_succeeded)
+  if (!copy_succeeded) {
+    ri->DeleteQueriesEXT(1, &query_id);
     return false;
+  }
 
-  IgnoreResult(failure_runner.Release());
+  // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame()
+  // texture copy before we access GMB data.
+  ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
+
   auto on_query_done_cb =
       [](scoped_refptr<media::VideoFrame> frame,
          base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> ctx_wrapper,
@@ -173,9 +173,6 @@
         std::move(callback).Run(std::move(frame));
       };
 
-  // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame()
-  // texture copy before we access GMB data.
-  ri->EndQueryEXT(GL_COMMANDS_COMPLETED_CHROMIUM);
   auto* context_support = raster_context_provider->ContextSupport();
   DCHECK(context_support);
   context_support->SignalQuery(
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
index 233b201..fbee97c 100644
--- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
+++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.h
@@ -53,14 +53,13 @@
       base::OnceCallback<void(scoped_refptr<media::VideoFrame>)>;
 
   // On success, this function will issue return true and will call the
-  // specified FrameCallback with the resulting VideoFrame when the frame
-  // is ready. On failure this will issue `callback` with a nullptr VideoFrame
-  // and then return false. The resulting VideoFrame will always be NV12.
-  // Note: In some paths `src_color_space` is ignored in favor of the
-  // SharedImage color space associated with `src_mailbox_holder`.
-  // Note: If the YUV to RGB matrix of `dst_color_space` is not Rec601, then
-  // this function will use the matrix for Rec709 (it supports no other
-  // values). See https://crbug.com/skia/12545.
+  // specified FrameCallback with the resulting VideoFrame when the frame is
+  // ready. On failure this will return false. The resulting VideoFrame will
+  // always be NV12. Note: In some paths `src_color_space` is ignored in favor
+  // of the SharedImage color space associated with `src_mailbox_holder`. Note:
+  // If the YUV to RGB matrix of `dst_color_space` is not Rec601, then this
+  // function will use the matrix for Rec709 (it supports no other values). See
+  // https://crbug.com/skia/12545.
   bool CopyRGBATextureToVideoFrame(viz::ResourceFormat src_format,
                                    const gfx::Size& src_size,
                                    const gfx::ColorSpace& src_color_space,
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index b830a45a..2bd04cb4 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -13,6 +13,8 @@
 # Tests that fail in legacy but pass in NG
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
 crbug.com/626703 external/wpt/preload/preload-referrer-policy.html [ Timeout ]
 crbug.com/626703 external/wpt/css/css-sizing/aspect-ratio/floats-aspect-ratio-001.html [ Failure ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-move-into-script-disabled-iframe.html [ Timeout ]
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
index 214a663..e586cbc 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
+++ b/third_party/blink/web_tests/FlagExpectations/disable-site-isolation-trials
@@ -44,6 +44,7 @@
 crbug.com/1209223 external/wpt/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-security-check-same-origin-domain.sub.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
 crbug.com/626703 external/wpt/preload/preload-referrer-policy.html [ Timeout ]
 crbug.com/626703 external/wpt/html/semantics/embedded-content/the-img-element/image-loading-lazy-move-into-script-disabled-iframe.html [ Timeout ]
 crbug.com/626703 external/wpt/content-security-policy/wasm-unsafe-eval/postMessage-wasm-module.html [ Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 0ddfcce..c118ddb8 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3343,6 +3343,14 @@
 crbug.com/626703 [ Win ] virtual/partitioned-cookies/http/tests/inspector-protocol/network/disabled-cache-navigation.js [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Mac10.15 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Mac11 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Mac11-arm64 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Mac12 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Mac12-arm64 ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 [ Win ] external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
+crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ]
 crbug.com/626703 [ Mac10.15 ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ]
 crbug.com/626703 [ Mac11 ] external/wpt/preload/preload-referrer-policy.html [ Skip Timeout ]
@@ -7097,4 +7105,4 @@
 
 # Sheriff 2022-06-08
 crbug.com/1229084 [ Linux ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ]
-crbug.com/1229084 [ Win ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ]
\ No newline at end of file
+crbug.com/1229084 [ Win ] external/wpt/storage-access-api/requestStorageAccess.sub.window.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index c085294..0bff7d7 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: a6101f13a28eb78dbef77e276ddee75052a8a2d4
+Version: c801c26f4182f6e2fbf72ac3093a3746d8d50400
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 cd5173a..78bcbf9a 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
@@ -4368,6 +4368,19 @@
      ]
     ]
    },
+   "service-workers": {
+    "cache-storage": {
+     "crashtests": {
+      "cache-response-clone.https.html": [
+       "ec930a87d934c4b232d42c9d411457a1776e86ca",
+       [
+        null,
+        {}
+       ]
+      ]
+     }
+    }
+   },
    "shadow-dom": {
     "event-on-pseudo-element-crash.html": [
      "c03f51a64f439e772ff56702dc132f8cd8c7938c",
@@ -86763,6 +86776,125 @@
         {}
        ]
       ],
+      "repeated-section": {
+       "abspos.tentative.html": [
+        "a7297f1dd559f5bb38a1143d0371d17d4ee29bba",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "block-in-inline.tentative.html": [
+        "1a94c697f15707efe09767c64b9c71a9103d78dc",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "captions.tentative.html": [
+        "1f28d56802cf2aa4f631c509510dd9761243bfc0",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "footer.tentative.html": [
+        "8789ef2915fd98bb21e58a4d221f87b8e78f0998",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "header-after-break.tentative.html": [
+        "6a5abc011fa20c0df1613055307aec47a26381e1",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "header-footer.tentative.html": [
+        "7a1e956a8dacf6b497f9e9d1a87a3f37255b6418",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "header.tentative.html": [
+        "6f4ad01097ea0525c7c513ae9f74ede800d7d7cf",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "inline-block.tentative.html": [
+        "6dee47e375752e73e63030fd0c27951b966683d8",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "multicol.tentative.html": [
+        "6dcd51bfe3e088262b407bd686a1db000771fdf7",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ]
+      },
       "section-with-overflow-000.html": [
        "909052765b6cc616389f52cb4e21857caeab38fd",
        [
@@ -88419,6 +88551,34 @@
        {}
       ]
      ],
+     "animation": {
+      "opacity-animation-ending-correctly-001.html": [
+       "1fb36cd366ff260f073c7de6d8062d9fceff5340",
+       [
+        null,
+        [
+         [
+          "/css/css-color/animation/opacity-animation-ending-correctly-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "opacity-animation-ending-correctly-002.html": [
+       "7ba097fb105ab683d6a8a7484007821a13a75a62",
+       [
+        null,
+        [
+         [
+          "/css/css-color/animation/opacity-animation-ending-correctly-001-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ]
+     },
      "at-color-profile-001.html": [
       "f2a971532c823dfe821a0eed1a9fe0e7a8631a71",
       [
@@ -150589,6 +150749,19 @@
        {}
       ]
      ],
+     "highlight-pseudos-currentcolor-inheritance-computed-002.html": [
+      "0d0da9ecec96f7357b1e7a6cd684abb9a1c56a6f",
+      [
+       null,
+       [
+        [
+         "/css/css-pseudo/reference/highlight-pseudos-currentcolor-inheritance-computed-002-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "highlight-styling-001.html": [
       "63d8ee1eda47dec0eeaf30f56316e4203e49f182",
       [
@@ -179769,6 +179942,19 @@
        {}
       ]
      ],
+     "text-decoration-color-recalc-002.html": [
+      "ce5c36dd5b6508c6d34ac0de5a5e65aa1c54fcf5",
+      [
+       null,
+       [
+        [
+         "/css/css-text-decor/text-decoration-color-recalc-002-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "text-decoration-color-recalc.html": [
       "c82bdcad73852b10842b7da568ca77b80ebe65a8",
       [
@@ -184736,6 +184922,34 @@
       ]
      ],
      "individual-transform": {
+      "animation": {
+       "individual-transform-combine.html": [
+        "9551a3a726a1c2e5dbee246be7258ba5e6db910f",
+        [
+         null,
+         [
+          [
+           "/css/css-transforms/individual-transform/animation/individual-transform-combine-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ],
+       "individual-transform-ordering.html": [
+        "9d127f163bc2b88ba4eedc28bf9eb143846b26c1",
+        [
+         null,
+         [
+          [
+           "/css/css-transforms/individual-transform/animation/individual-transform-ordering-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
+       ]
+      },
       "individual-transform-1.html": [
        "f21954e01dfc0f8f70c9dd43262d40b3374010b5",
        [
@@ -193685,6 +193899,19 @@
      ]
     },
     "css-transitions": {
+     "inherit-background-color-transition.html": [
+      "2c0e4aed933ec69f145f55dac81f262d93a3cdaa",
+      [
+       null,
+       [
+        [
+         "/css/css-transitions/inherit-background-color-transition-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "no-transition-from-ua-to-blocking-stylesheet.html": [
       "4967eabda86bf42be467b826f8782e91a115748e",
       [
@@ -244002,7 +244229,7 @@
        ]
       ],
       "transform-dynamic-change.html": [
-       "abd05cce16e7b9cd3b021467420087a648f4e32f",
+       "57b5551061945931b39f35394e2974b2306e2762",
        [
         null,
         [
@@ -262173,6 +262400,12 @@
       "3b8771a704a5f79e7062f790c04f0bbd24efb05b",
       []
      ],
+     "animation": {
+      "opacity-animation-ending-correctly-001-ref.html": [
+       "ca55dc66f3007a6104b0298d77a215e1d6f2c123",
+       []
+      ]
+     },
      "background-color-hsl-001-ref.html": [
       "f37a73d1707f056962baad29a2198fd3b271e362",
       []
@@ -281040,6 +281273,10 @@
        "b3c89177591ad83476edd3616f135f1cd65700d8",
        []
       ],
+      "highlight-pseudos-currentcolor-inheritance-computed-002-ref.html": [
+       "67ecb8df640f72e1725e42a648f2c6e1f33490e2",
+       []
+      ],
       "placeholder-excluded-properties-ref.html": [
        "0e573cb3d6cbac837c9e10552e360aa713fee60b",
        []
@@ -287343,6 +287580,10 @@
        []
       ]
      },
+     "text-decoration-color-recalc-002-ref.html": [
+      "440d2f051cae91b62ff33b454646306dcbd05f0f",
+      []
+     ],
      "text-decoration-line-grammar-error-color-001-ref.html": [
       "2592110a1199515b6376d21a963132bfe90400bc",
       []
@@ -287786,6 +288027,16 @@
       []
      ],
      "individual-transform": {
+      "animation": {
+       "individual-transform-combine-ref.html": [
+        "7c8eb206a9fb7fc9a4cf53f5282cfc1fb251d450",
+        []
+       ],
+       "individual-transform-ordering-ref.html": [
+        "b7dce51e8bab9e5985426d8b8d16966557eef742",
+        []
+       ]
+      },
       "individual-transform-1-ref.html": [
        "dbc5f05d8925a8ddd37c8a6499b0563d4fdaf71e",
        []
@@ -289013,6 +289264,10 @@
       "f72f11dccae5e8b63de6148573723f86fbb4c708",
       []
      ],
+     "inherit-background-color-transition-ref.html": [
+      "b7a5824836e157f21649fabe12a701b860e04c9f",
+      []
+     ],
      "no-transition-from-ua-to-blocking-stylesheet-ref.html": [
       "93b4ae982e80d31df4cb0eac448ceb3341c57a81",
       []
@@ -289121,7 +289376,7 @@
        []
       ],
       "properties.js": [
-       "3255261f6c604ee2bdfc3b07f6acd917408cd677",
+       "93c47cd2f0310cbe445ec4bdcce29534275adde6",
        []
       ],
       "ruler-h-50%.png": [
@@ -295875,7 +296130,7 @@
      []
     ],
     "OWNERS": [
-     "73c81fa31d15b0276bb6c8e59002a8ab94031899",
+     "167a625063bc31c6e7d58df13f8561ed28931b29",
      []
     ],
     "README.md": [
@@ -301718,10 +301973,6 @@
        "9885466ebb5540246b80fcf39dbd461ab6cd5721",
        []
       ],
-      "delegate-request-subframe.html": [
-       "9bb9d7816d45289f10589bb5ae8d998b44efd1e9",
-       []
-      ],
       "echo-fullscreenEnabled.html": [
        "ad5edf79866273d0debb2dbc438e6dec6f305cd3",
        []
@@ -305293,7 +305544,7 @@
          []
         ],
         "fill-and-stroke-styles.yaml": [
-         "f52a3e24c61e527d620066720f75443e99406236",
+         "16c8aa52c5ceae08b828ea2cd2fcec6a626edf38",
          []
         ],
         "line-styles.yaml": [
@@ -305335,7 +305586,7 @@
        },
        "offscreen": {
         "fill-and-stroke-styles.yaml": [
-         "7a57a4730e096c728010b754c503c753a6972326",
+         "c70082cf6d2d700ea91080a969dfbffdb5ebf4eb",
          []
         ],
         "line-styles.yaml": [
@@ -305416,6 +305667,18 @@
       }
      }
     },
+    "capability-delegation": {
+     "resources": {
+      "delegate-fullscreen-request-recipient.html": [
+       "11daf738d6856d72b6a575639915443659785df3",
+       []
+      ],
+      "utils.js": [
+       "3add3eb6f50eb97c857e561a4cb43bd3c29c31ab",
+       []
+      ]
+     }
+    },
     "cross-origin-embedder-policy": {
      "META.yml": [
       "dc7010880b61d455c7ecdc43cbc2a4e00081bd19",
@@ -305771,7 +306034,15 @@
       "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
       []
      ],
-     "coep.https.html.headers": [
+     "coep-with-cross-origin.https.html.headers": [
+      "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
+      []
+     ],
+     "coep-with-same-origin.https.html.headers": [
+      "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
+      []
+     ],
+     "coep-with-same-site.https.html.headers": [
       "63b60e490f47f4db77d33d7a4ca2f5b9a4181de8",
       []
      ],
@@ -305990,7 +306261,7 @@
       },
       "resources": {
        "reporting-common.js": [
-        "6ed75b2c5715e2466bbd8e946a8edacd74667b73",
+        "585287d39dd644fc4a76dabff743c46ecfb03102",
         []
        ],
        "test-access-property.js": [
@@ -306009,7 +306280,7 @@
        []
       ],
       "common.js": [
-       "34589f40d93496e2b61864af9ae77fb945eca83d",
+       "ff6be1bbe53545e4ef64b31e7969e640cf59c3b0",
        []
       ],
       "coop-coep.py": [
@@ -306037,7 +306308,7 @@
        []
       ],
       "popup-test.js": [
-       "3da5ca11fe5881a6bd228e1c3757bf6523becc62",
+       "f613a9f770d0de62730d1a023691f01acf5b5162",
        []
       ],
       "postback.html": [
@@ -309695,7 +309966,7 @@
          []
         ],
         "iframe-domain-failure.sub.html": [
-         "9fea70380547e12492cb472612cab379d5bbd560",
+         "0cdb8b5f5955b46aed32099db1aed9b823c09aad",
          []
         ],
         "iframe-domain-failure.sub.html.headers": [
@@ -311132,6 +311403,14 @@
        "c1dd8dddf9eec3ab3fb58df01c549c251f3a3fdf",
        []
       ],
+      "bfcache": {
+       "resources": {
+        "common.js": [
+         "9c852bbfb3ed1d607b69de96fb3717cb4725e23e",
+         []
+        ]
+       }
+      },
       "image-maps": {
        "image-map-processing-model": {
         "hash-name-reference-test-data.html": [
@@ -318456,7 +318735,7 @@
     ]
    },
    "lint.ignore": [
-    "fdba97deda7a6eb41a7209caae79371b2dd10917",
+    "07ad220e4f7d1bd7949842ad37827cca99b6eb9f",
     []
    ],
    "loading": {
@@ -321403,7 +321682,7 @@
      []
     ],
     "navigation-id.helper.js": [
-     "fd6e24d5c584f0871a800e6b410e7baea8a1a559",
+     "53099cadb254df0a4d087bc9dd75340b5ddb40fa",
      []
     ],
     "performanceobservers.js": [
@@ -321415,6 +321694,18 @@
       "e69de29bb2d1d6434b8b29ae775ad8c2e48c5391",
       []
      ],
+     "json_resource.json": [
+      "68b6ac1d56f7c25d29f01cc020bda162389776bf",
+      []
+     ],
+     "make_long_task.js": [
+      "a52d6d839298ccbd3c984984a3038c7797cccc34",
+      []
+     ],
+     "navigation-id-detached-frame-page.html": [
+      "02aafbb5c78368c69dbf1cdae81b432d988e17d1",
+      []
+     ],
      "postmessage-entry.html": [
       "ef5be73395b49d895a2589be547a7f3950f416ba",
       []
@@ -322391,6 +322682,10 @@
       "e4e3217b8c14ce97c7888000676f7e46e771ac70",
       []
      ],
+     "modulepreload-iframe.html": [
+      "1d3d21f4d953ee1eac4fbc93e91f4a404d5f0c8f",
+      []
+     ],
      "preload_helper.js": [
       "1c7c1a2750e7bc8dbd24ec16f4037183a4a9e91d",
       []
@@ -324738,7 +325033,7 @@
       []
      ],
      "mock-subapps.js": [
-      "dd6899a597b154b487fd50304a60a2469dfb7ba5",
+      "96ddcfd246f28977ded46cbac0bfb73785e5628f",
       []
      ],
      "mock-textdetection.js": [
@@ -328404,7 +328699,11 @@
        "1ab609f11bf2be22696f0b132b88d8fc86546b93",
        []
       ],
-      "notification.html": [
+      "notification-before-activation.html": [
+       "16aab488a572506abda901d89384e3798c7670ca",
+       []
+      ],
+      "notification-on-activation.html": [
        "03e36f06c134e1ee0ced6c703d1b8e20f1c7511b",
        []
       ],
@@ -329593,7 +329892,7 @@
        []
       ],
       "transform-dynamic-change-ref.html": [
-       "cdcad92fe1f46bc3f76a1e0ac2c253122d1a2590",
+       "df8afcebc18e912d3c4a66be7e069f1a827e1e88",
        []
       ],
       "tspan-opacity-mixed-direction-ref.svg": [
@@ -330529,7 +330828,7 @@
      []
     ],
     "viewport_support.js": [
-     "5cea91a0155ae5c1de213ef96260d884361d9fba",
+     "7da5670d9027249e444f05badae048874a702bc7",
      []
     ]
    },
@@ -358040,7 +358339,7 @@
    },
    "clipboard-apis": {
     "async-custom-formats-write-read.tentative.https.html": [
-     "b6c368f75bc2f2902b9a5cd09e52871461daa8d0",
+     "77991ec98aa098e92cd13c01ff54468e6ccf8f1b",
      [
       null,
       {
@@ -358049,7 +358348,7 @@
      ]
     ],
     "async-html-script-removal.https.html": [
-     "90dc44c9db20e31ceae6bead41b956754cfe9d9d",
+     "44c11add855137ed00634c4435e758fa8c548067",
      [
       null,
       {
@@ -358065,7 +358364,7 @@
      ]
     ],
     "async-navigator-clipboard-read-resource-load.https.html": [
-     "5f74be1a8228273350f8793ce2ac8325c1335130",
+     "d1e3019e7f939965f6814436752e92a44ecb1b25",
      [
       null,
       {
@@ -358074,7 +358373,7 @@
      ]
     ],
     "async-navigator-clipboard-read-sanitize.https.html": [
-     "9e0ab2ee740f85ea4e9de9d3f1d2ac43bee5a985",
+     "cc1836753478b79972627b87bb3bca1e75c29459",
      [
       null,
       {
@@ -358083,7 +358382,7 @@
      ]
     ],
     "async-promise-write-blobs-read-blobs.https.html": [
-     "e4b93c7c5ffb7c0fc2fb0fb9d95932788177dda1",
+     "12184c92e0777f5d10a63ad8e075e8422d5545a5",
      [
       null,
       {
@@ -358092,7 +358391,7 @@
      ]
     ],
     "async-svg-script-removal.https.html": [
-     "cd1a551d9d12852f3ff8233bf535eb29e88c48ef",
+     "292d100b2fc7d2274a9e1bbf3dec85ed67f4fb32",
      [
       null,
       {
@@ -358101,7 +358400,7 @@
      ]
     ],
     "async-unsanitized-html-formats-write-read.tentative.https.html": [
-     "887ba8a484fd97c0956f70c85138099223be493c",
+     "ffe6a31c2a7a9382796b1917d724eb4b1ac13fd5",
      [
       null,
       {
@@ -358110,7 +358409,7 @@
      ]
     ],
     "async-unsanitized-plaintext-formats-write-read.tentative.https.html": [
-     "f44ed22618e2fd0c2781f959140d3d4d22cd45e9",
+     "1c5638ca0a5faf806ed9d003b6c36f20bedcb263",
      [
       null,
       {
@@ -358119,7 +358418,7 @@
      ]
     ],
     "async-write-blobs-read-blobs.https.html": [
-     "50d23a9c3625d5295407a783ad63908571fd55f7",
+     "8bec558b2b2de8a38c0f9620942a5307c8158665",
      [
       null,
       {
@@ -358128,7 +358427,7 @@
      ]
     ],
     "async-write-html-read-html.https.html": [
-     "7c271b9bd78d1b68b86a911923789c32f02210fe",
+     "ec1817c027bbc19304cfbd01034b4fbd2b54454c",
      [
       null,
       {
@@ -358137,7 +358436,7 @@
      ]
     ],
     "async-write-image-read-image.https.html": [
-     "281358dfc5f8d68d3d6d436fdd92dbc8fb8b7b5d",
+     "e10b69d824c20394ab151fc6ce1bd7c6260e76e9",
      [
       null,
       {
@@ -358146,7 +358445,7 @@
      ]
     ],
     "async-write-svg-read-svg.https.html": [
-     "19c91597c111ee267e95f6d4bb0092fa2aafec25",
+     "42f6c547b2979947c437a9b515f7ade9f1faf138",
      [
       null,
       {
@@ -358195,7 +358494,7 @@
       ]
      ],
      "write-read-on-detached-iframe.https.html": [
-      "c0f11772929eed601c1fc8e921ea3d933ba6444f",
+      "b21e6b20bc0d9940d35994e2867d415102fe8b76",
       [
        null,
        {
@@ -358204,7 +358503,7 @@
       ]
      ],
      "writeText-readText-on-detached-iframe.https.html": [
-      "9cd8900aab0f9ee9399b5fdb1c175563a06884ea",
+      "24fa586fc7709b72ef651b22f680ea290018c265",
       [
        null,
        {
@@ -358236,7 +358535,7 @@
        ]
       ],
       "clipboard-read-enabled-by-feature-policy-attribute-cross-origin-tentative.https.sub.html": [
-       "3b1cfd52ad7c9f4166fa9e529c80a227dd93bbb3",
+       "367d033d0f6afa1c2a9c6a0048444e012118656d",
        [
         null,
         {
@@ -358245,7 +358544,7 @@
        ]
       ],
       "clipboard-read-enabled-by-feature-policy-attribute-tentative.https.sub.html": [
-       "15d268426163727a3dbf2adbb01db40ea7fecd1f",
+       "e812854b4c75053f7350ba6b8864e5649dac9214",
        [
         null,
         {
@@ -358254,7 +358553,7 @@
        ]
       ],
       "clipboard-read-enabled-by-feature-policy-cross-origin-tentative.https.sub.html": [
-       "1b6f4929a19deaf7779643944fb7f90020235ff4",
+       "c371ea3b41cb2e648202f1aaf76b542fa0f033f8",
        [
         null,
         {
@@ -358263,7 +358562,7 @@
        ]
       ],
       "clipboard-read-enabled-by-feature-policy.tentative.https.sub.html": [
-       "f8c5bcb129f9324056ad57368dab3a85b982117c",
+       "552183cc67d461a61541d803ade89ebc729778a4",
        [
         null,
         {
@@ -358272,7 +358571,7 @@
        ]
       ],
       "clipboard-read-enabled-on-self-origin-by-feature-policy.tentative.https.sub.html": [
-       "47aa6511ec599be99f685b5a419511b81ee0baef",
+       "17dc3628a7722047f07997d0a8544a9599f75bf3",
        [
         null,
         {
@@ -358292,7 +358591,7 @@
        ]
       ],
       "clipboard-write-enabled-by-feature-policy-attribute-cross-origin-tentative.https.sub.html": [
-       "c931bbbb89f32f8035cac150d0eb658e31e8bf8b",
+       "e669c8fec4910dc8f3f7a038b69f0b17e671c94a",
        [
         null,
         {
@@ -358301,7 +358600,7 @@
        ]
       ],
       "clipboard-write-enabled-by-feature-policy-attribute-tentative.https.sub.html": [
-       "a2858c638e6c05f08ea8d4b71dd8891a21b63b43",
+       "b57dfe3dd2888dcaace721a10aeda58ee8e03ee9",
        [
         null,
         {
@@ -358310,7 +358609,7 @@
        ]
       ],
       "clipboard-write-enabled-by-feature-policy-cross-origin-tentative.https.sub.html": [
-       "0f3164d9b02a13f8d5296bdbdd65b11041889a13",
+       "6e7029cc789a63e0603b596739ca6eac36bbdc88",
        [
         null,
         {
@@ -358319,7 +358618,7 @@
        ]
       ],
       "clipboard-write-enabled-by-feature-policy.tentative.https.sub.html": [
-       "1c6fc49a056605a1dfab3fb96cd1155ea72716c7",
+       "ca97994c617d0ee751672be28eaaf30b59283a66",
        [
         null,
         {
@@ -358328,7 +358627,7 @@
        ]
       ],
       "clipboard-write-enabled-on-self-origin-by-feature-policy.tentative.https.sub.html": [
-       "51db5a427d2b4140786555e07c7f57624a8ae505",
+       "5615a68ac55af819759d1bbd214ac940289ceb39",
        [
         null,
         {
@@ -358363,7 +358662,7 @@
     ],
     "permissions": {
      "readText-denied.https.html": [
-      "935f520e7de2dd15e0019c798dd0966c454235cd",
+      "010f4ba21b95332c3fabb59c2861b634e1ea48ee",
       [
        null,
        {
@@ -358372,7 +358671,7 @@
       ]
      ],
      "readText-granted.https.html": [
-      "ab76cd5e1da86e830829c45d876ae3e016a573f3",
+      "e912bd64a83148baaaaffa1214ccc0ba37fa3e44",
       [
        null,
        {
@@ -358381,7 +358680,7 @@
       ]
      ],
      "writeText-denied.https.html": [
-      "4d0530f0bc221773606b27b119d0b20100444703",
+      "5fbcab411748e25170c06da87d8ff7930cfa6b7d",
       [
        null,
        {
@@ -358390,7 +358689,7 @@
       ]
      ],
      "writeText-granted.https.html": [
-      "b03ae7ff26b59cbd00ec1a25a6953023b139ee71",
+      "ff347b7adda0727a07e9e76df9adb482eae746bd",
       [
        null,
        {
@@ -358401,7 +358700,7 @@
     },
     "text-write-read": {
      "async-write-read.https.html": [
-      "a00c5b27a4d65f148d3cafaf4700a0e3e286cfee",
+      "c46e5d43171314132ab0be20a93a1f50e9b25b64",
       [
        null,
        {
@@ -358410,7 +358709,7 @@
       ]
      ],
      "async-write-readText.https.html": [
-      "e8156af47f4c34395136c463ecb1dae2cd8c9870",
+      "66969b1777b251ebc7413e59453c9857a0f7b5b7",
       [
        null,
        {
@@ -358419,7 +358718,7 @@
       ]
      ],
      "async-writeText-read.https.html": [
-      "4a37aa1a5f73d3b9521145637c2bbbaf35dd2e96",
+      "ddf563269a422a578fc4c7206810790c9f090e30",
       [
        null,
        {
@@ -358428,7 +358727,7 @@
       ]
      ],
      "async-writeText-readText.https.html": [
-      "7e56bfef2c684415eaaa4e62bcde77232fa8531f",
+      "0defdf7a709535020f24c674796d8a9b9bf0dd4b",
       [
        null,
        {
@@ -369942,6 +370241,13 @@
         {}
        ]
       ],
+      "animation-timing-function-linear.tentative.html": [
+       "007d7a10aeae233b072ad04ee2725a2b2004088a",
+       [
+        null,
+        {}
+       ]
+      ],
       "animation-timing-function-valid.html": [
        "7ab823ea1da1535606ac4aad30fb21f423ba6703",
        [
@@ -371130,6 +371436,13 @@
        {}
       ]
      ],
+     "offset-top-block-in-inline.html": [
+      "72b35087e424cbf13289686dcc9436309320b27e",
+      [
+       null,
+       {}
+      ]
+     ],
      "overflow-clip-007.html": [
       "a90cba2f846442195c18f88f0b0607f48769374d",
       [
@@ -379601,6 +379914,13 @@
        {}
       ]
      ],
+     "object-view-box-interpolation.html": [
+      "18ac72db70d63a78f2f61ea358adb3396631042b",
+      [
+       null,
+       {}
+      ]
+     ],
      "object-view-box-parsing.html": [
       "da17b7936fb9a3552ce263369c84282df30a4c23",
       [
@@ -384058,6 +384378,13 @@
        {}
       ]
      ],
+     "snap-on-focus.html": [
+      "b8763992055fd700a21a743b562acf4bff858227",
+      [
+       null,
+       {}
+      ]
+     ],
      "snap-to-transformed-target.html": [
       "b8604269b4b9a1d6dbf337cfe867714cbf40fabb",
       [
@@ -417571,6 +417898,16 @@
       }
      ]
     ],
+    "first-input-interactionid-tap.html": [
+     "c5c6f5177ebd9882c41385000c9bb3d08f3e8567",
+     [
+      null,
+      {
+       "testdriver": true,
+       "timeout": "long"
+      }
+     ]
+    ],
     "first-input-shadow-dom.html": [
      "5911dabd54e65f34b04eb40f2e99dd0089047e66",
      [
@@ -432660,15 +432997,6 @@
    },
    "fullscreen": {
     "api": {
-     "delegate-request.https.sub.tentative.html": [
-      "37e0099e6a8692ac24a531814cd3324c0b71e8d5",
-      [
-       null,
-       {
-        "testdriver": true
-       }
-      ]
-     ],
      "document-exit-fullscreen-active-document.html": [
       "8279fae533774fcf6daced99ffc84413a0a9172d",
       [
@@ -440056,6 +440384,13 @@
          {}
         ]
        ],
+       "2d.fillStyle.get.halftransparent.html": [
+        "4101bf4ce9d5ff6501dc38fe14f83d6198b9ce12",
+        [
+         null,
+         {}
+        ]
+       ],
        "2d.fillStyle.get.semitransparent.html": [
         "9f1784730977e29d12122f6e62514afe847de59c",
         [
@@ -447870,6 +448205,20 @@
          {}
         ]
        ],
+       "2d.fillStyle.get.halftransparent.html": [
+        "47e555547e839d7fe688fe9bf2cb6695d4c6b67a",
+        [
+         null,
+         {}
+        ]
+       ],
+       "2d.fillStyle.get.halftransparent.worker.js": [
+        "ec66b5868c8e5613d84944c10432fc5276b530dd",
+        [
+         "html/canvas/offscreen/fill-and-stroke-styles/2d.fillStyle.get.halftransparent.worker.html",
+         {}
+        ]
+       ],
        "2d.fillStyle.get.semitransparent.html": [
         "9f8566809d9024d8e05c9a2a1a192fa169a504b6",
         [
@@ -457905,6 +458254,53 @@
       }
      }
     },
+    "capability-delegation": {
+     "delegate-fullscreen-request-popup-cross-origin.https.sub.tentative.html": [
+      "2d531a5d983500567119617a05edb773a0232861",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
+     "delegate-fullscreen-request-popup-same-origin.https.tentative.html": [
+      "d429095cfcbbdddb5b651b713669770b0cb23863",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
+     "delegate-fullscreen-request-subframe-cross-origin.https.sub.tentative.html": [
+      "5f2d2f61c97aab3a168a3baafd120db78505ce61",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
+     "delegate-fullscreen-request-subframe-same-origin.https.tentative.html": [
+      "9e5482dc183e42b5f3fd9284fe43d7229bca01e1",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ],
+     "delegation-consumes-activation.https.tentative.html": [
+      "1a8805de486d24cbce75bff0ba0792fd3b3d0712",
+      [
+       null,
+       {
+        "testdriver": true
+       }
+      ]
+     ]
+    },
     "cross-origin-embedder-policy": {
      "about-blank-popup.https.html": [
       "2dc73c7561ff297ea2cf50c67d8218fef941a194",
@@ -459312,8 +459708,26 @@
        }
       ]
      ],
-     "coep.https.html": [
-      "f6d975564f4fd0a5d272ea6977b7aa93c64e4794",
+     "coep-with-cross-origin.https.html": [
+      "3f6256bcd283b2e9c16839aede42ec79f7992b2f",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "coep-with-same-origin.https.html": [
+      "66e7aaf88e5279fc3b56beec235bbeb883370b8e",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "coep-with-same-site.https.html": [
+      "abce6597901ad52a92e0aa5f4187acec06cbad26",
       [
        null,
        {
@@ -459403,7 +459817,7 @@
       ]
      ],
      "header-parsing-failures.https.html": [
-      "1973550103225d8843cd52d796e13aa64d228a78",
+      "55b126ff379b1071cc22b4a1fa706865824550f3",
       [
        "html/cross-origin-opener-policy/header-parsing-failures.https.html?1-4",
        {
@@ -459444,7 +459858,7 @@
       ]
      ],
      "header-parsing-successes.https.html": [
-      "0d3dadb4ce26b6ed0a4f203818bdf450718162dd",
+      "8e055669ad845bf7437056b111b5f5f9fe925efa",
       [
        null,
        {
@@ -459463,7 +459877,7 @@
        ]
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-cross-origin.https.html": [
-       "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f",
+       "21e0875f41b020c454d0ae0efceaa036934f2e89",
        [
         null,
         {
@@ -459472,7 +459886,7 @@
        ]
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-same-origin.https.html": [
-       "1a09d5996faf24c650aa22bb4b3b93c053cb10d7",
+       "89b0b4934ea4bfaf223d8f0929f494df3dea79db",
        [
         null,
         {
@@ -459481,7 +459895,7 @@
        ]
       ],
       "popup-same-origin-unsafe-allow-outgoing-with-same-site.https.html": [
-       "e884d21622bdb851bf09731bc86ef6eb05f7cb25",
+       "fb3330365fbf4b1c743bdc132084b7f326d352fc",
        [
         null,
         {
@@ -459490,7 +459904,7 @@
        ]
       ],
       "popup-same-site-unsafe-allow-outgoing-with-cross-origin.https.html": [
-       "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f",
+       "21e0875f41b020c454d0ae0efceaa036934f2e89",
        [
         null,
         {
@@ -459499,7 +459913,7 @@
        ]
       ],
       "popup-same-site-unsafe-allow-outgoing-with-same-origin.https.html": [
-       "1a09d5996faf24c650aa22bb4b3b93c053cb10d7",
+       "89b0b4934ea4bfaf223d8f0929f494df3dea79db",
        [
         null,
         {
@@ -459508,7 +459922,7 @@
        ]
       ],
       "popup-same-site-unsafe-allow-outgoing-with-same-site.https.html": [
-       "e884d21622bdb851bf09731bc86ef6eb05f7cb25",
+       "fb3330365fbf4b1c743bdc132084b7f326d352fc",
        [
         null,
         {
@@ -459517,7 +459931,7 @@
        ]
       ],
       "popup-same-site-with-cross-origin.https.html": [
-       "d45d9e4a086aece4531b36ccbf64e4bca12d1c0f",
+       "21e0875f41b020c454d0ae0efceaa036934f2e89",
        [
         null,
         {
@@ -459526,7 +459940,7 @@
        ]
       ],
       "popup-same-site-with-same-origin.https.html": [
-       "1a09d5996faf24c650aa22bb4b3b93c053cb10d7",
+       "89b0b4934ea4bfaf223d8f0929f494df3dea79db",
        [
         null,
         {
@@ -459535,7 +459949,7 @@
        ]
       ],
       "popup-same-site-with-same-site.https.html": [
-       "e884d21622bdb851bf09731bc86ef6eb05f7cb25",
+       "fb3330365fbf4b1c743bdc132084b7f326d352fc",
        [
         null,
         {
@@ -459734,7 +460148,7 @@
       ]
      ],
      "popup-same-origin-allow-popups-with-cross-origin.https.html": [
-      "c776f4450ff221ce286af9eeeb3ba9f1edba0db1",
+      "d025faeb67ee0b2bd2d7616a7c6619d5a6d61dd8",
       [
        null,
        {
@@ -459743,7 +460157,7 @@
       ]
      ],
      "popup-same-origin-allow-popups-with-same-origin.https.html": [
-      "7e14d072774c3a1536449287f92985056bbd249b",
+      "438e4242848ffb7d383919279dd001d5cfe2c2c6",
       [
        null,
        {
@@ -459752,7 +460166,7 @@
       ]
      ],
      "popup-same-origin-allow-popups-with-same-site.https.html": [
-      "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24",
+      "d1b6b60d7c8232ee4fa5d46445e8870727127d5b",
       [
        null,
        {
@@ -459768,7 +460182,7 @@
       ]
      ],
      "popup-same-origin-with-cross-origin.https.html": [
-      "a01ab56d173137aa25abba811ffceddae393c300",
+      "bd1e6848c4bfe823e4bcdc7b548c667684fd98da",
       [
        null,
        {
@@ -459777,7 +460191,7 @@
       ]
      ],
      "popup-same-origin-with-same-origin.https.html": [
-      "b103bb7308a6ec6c6200ae795b55a7eeaba18927",
+      "caf4b173c28b348f412c358021a85df0a56964a6",
       [
        null,
        {
@@ -459786,7 +460200,7 @@
       ]
      ],
      "popup-same-origin-with-same-site.https.html": [
-      "3ed8b1cd014344f16d468f65c5500aeb300a95f3",
+      "93ba9c9888cf1885545c3b0ac57fbee8b8b105f4",
       [
        null,
        {
@@ -459795,7 +460209,7 @@
       ]
      ],
      "popup-unsafe-none-with-cross-origin.https.html": [
-      "c776f4450ff221ce286af9eeeb3ba9f1edba0db1",
+      "31ac5694913b7957ab7f7f20fcea499ae590ccb9",
       [
        null,
        {
@@ -459804,7 +460218,7 @@
       ]
      ],
      "popup-unsafe-none-with-same-origin.https.html": [
-      "7b3f4d94718e79bf6f748c99aa3075640a57ee67",
+      "18f87048c30b65155e04dbbf3450f379adb91ddf",
       [
        null,
        {
@@ -459813,7 +460227,7 @@
       ]
      ],
      "popup-unsafe-none-with-same-site.https.html": [
-      "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24",
+      "d1b6b60d7c8232ee4fa5d46445e8870727127d5b",
       [
        null,
        {
@@ -459822,7 +460236,7 @@
       ]
      ],
      "popup-unspecified-with-cross-origin.https.html": [
-      "c776f4450ff221ce286af9eeeb3ba9f1edba0db1",
+      "31ac5694913b7957ab7f7f20fcea499ae590ccb9",
       [
        null,
        {
@@ -459831,7 +460245,7 @@
       ]
      ],
      "popup-unspecified-with-same-origin.https.html": [
-      "7b3f4d94718e79bf6f748c99aa3075640a57ee67",
+      "18f87048c30b65155e04dbbf3450f379adb91ddf",
       [
        null,
        {
@@ -459840,7 +460254,7 @@
       ]
      ],
      "popup-unspecified-with-same-site.https.html": [
-      "7d734fa27f2603f6c4a1cdeefa1d29623f3d5d24",
+      "d1b6b60d7c8232ee4fa5d46445e8870727127d5b",
       [
        null,
        {
@@ -459849,7 +460263,7 @@
       ]
      ],
      "popup-with-structured-header.https.html": [
-      "729be3c4aade82c4ede2c52a9b328f70ec2cd181",
+      "e337e69cc0c67b565af7aceeae87ebe93410f766",
       [
        null,
        {
@@ -461832,7 +462246,7 @@
         ]
        ],
        "window-domain-failure.https.sub.html": [
-        "2deff50d8dd91642f337ae19a3df733837fe8c83",
+        "6fa196e094e9b5ed6011f46bc1a75b66c1870d01",
         [
          null,
          {}
@@ -465103,6 +465517,50 @@
       }
      },
      "embedded-content": {
+      "bfcache": {
+       "embeded-html.html": [
+        "0808538337710337f9dc8705bf1c951266b027f8",
+        [
+         null,
+         {}
+        ]
+       ],
+       "embeded-img.html": [
+        "7e9d713c0a79cb64d99cb2b27c32c60713453d59",
+        [
+         null,
+         {}
+        ]
+       ],
+       "embeded-js.html": [
+        "c3b027563d32e55ada6d45bfddc43afe0640e87a",
+        [
+         null,
+         {}
+        ]
+       ],
+       "embeded-mp4.html": [
+        "fde560e5be95dfb067cd54aa5bad303e59b32e6e",
+        [
+         null,
+         {}
+        ]
+       ],
+       "embeded-not-found.html": [
+        "0b56b5eadc536b131f386ab2724637d024e8f204",
+        [
+         null,
+         {}
+        ]
+       ],
+       "embeded-type-only.html": [
+        "90c9d3311c3096c646d628c75402106afeb54470",
+        [
+         null,
+         {}
+        ]
+       ]
+      },
       "image-maps": {
        "image-map-processing-model": {
         "hash-name-reference.html": [
@@ -471348,15 +471806,6 @@
          {}
         ]
        ],
-       "selectmenu-shadow-root-replacement.tentative.html": [
-        "b505e58ee2837b922616ee8d594c2c790fc185cd",
-        [
-         null,
-         {
-          "testdriver": true
-         }
-        ]
-       ],
        "selectmenu-validity.tentative.html": [
         "a58fe54ff6a28b33574996db863f7cbd20c31b8f",
         [
@@ -472366,11 +472815,12 @@
        ]
       ],
       "popup-light-dismiss.tentative.html": [
-       "a5401cd426b1380fd18e93511335cee21411260c",
+       "10317a8f35d6555f28305e54d92ff8c5f0bc68bc",
        [
         null,
         {
-         "testdriver": true
+         "testdriver": true,
+         "timeout": "long"
         }
        ]
       ],
@@ -474476,6 +474926,13 @@
            {}
           ]
          ],
+         "delay-load-event.html": [
+          "5ec6433e65b59c026209964002a8db47f3f97a94",
+          [
+           null,
+           {}
+          ]
+         ],
          "dynamic-imports-credentials-setTimeout.sub.html": [
           "189aa819fa53a5e701969429ff596863e7f0a84c",
           [
@@ -480422,7 +480879,7 @@
          ]
         ],
         "document-synthetic-errorevent.html": [
-         "8b1b3cfb5b2c33c07da64e02f3c160cce748e2f7",
+         "a541611909767a58300846613ecbc530b7f68bdd",
          [
           null,
           {}
@@ -485934,14 +486391,14 @@
      },
      "mrow": {
       "inferred-mrow-baseline.html": [
-       "2b208aa8b026bbb30ecc1e5984853a2a06043fb9",
+       "cc007cf81ff823890a59ccec5c285f3b23853b4b",
        [
         null,
         {}
        ]
       ],
       "inferred-mrow-stretchy.html": [
-       "35c6d699ccb2dbced9e28e43885d38e778f23041",
+       "a1e409a248e9075e697a2a31208f40a009e66440",
        [
         null,
         {}
@@ -485983,7 +486440,7 @@
        ]
       ],
       "spacing.html": [
-       "bad3370ca5b8d57ecb102a6e746e08afefd312ec",
+       "c066f72cde22face93a56946bf6dffe9b2627ae5",
        [
         null,
         {}
@@ -486556,6 +487013,13 @@
         {}
        ]
       ],
+      "table-cell-mrow-layout.html": [
+       "1e76e3949a5bb1db505fd1c841d69431f5423281",
+       [
+        null,
+        {}
+       ]
+      ],
       "table-default-styles-001.html": [
        "495cdc000af5cecdc0892be59c0313c61c322d7f",
        [
@@ -486784,7 +487248,7 @@
        ]
       ],
       "dynamic-childlist-002.html": [
-       "e4b4313d6fc0e9138f4c36540537e03800002699",
+       "099401eaccc0524d514c6203f360d6c682d2b089",
        [
         null,
         {}
@@ -488487,8 +488951,8 @@
     }
    },
    "mediacapture-region": {
-    "MediaDevices-produceCropId.https.html": [
-     "af8c659a5ba0d771f9ff46813e4cf50011580975",
+    "CropTarget-fromElement.https.html": [
+     "fb0393bda536a79fdd272b1eb10e5597499defdb",
      [
       null,
       {}
@@ -495294,7 +495758,7 @@
       ]
      ],
      "same-document-away-and-back-navigation-api.html": [
-      "0ece14d4b7d3bc61fa5f6cffff6ea3297ce5edc5",
+      "220908e4c46cb91ad24408078ef1f7846b45e1b6",
       [
        null,
        {}
@@ -497514,8 +497978,42 @@
       {}
      ]
     ],
-    "navigation-id.tentative.html": [
-     "08dbd4b01b1359b8af3971e03cb33743e12d58fa",
+    "navigation-id-detached-frame.tentative.html": [
+     "add11255af45c00a596f8e34e909a3304a92881b",
+     [
+      null,
+      {}
+     ]
+    ],
+    "navigation-id-element-timing.tentative.html": [
+     "bc52f208b0726421f1d36cdc6b737030c0760c1d",
+     [
+      null,
+      {
+       "timeout": "long"
+      }
+     ]
+    ],
+    "navigation-id-long-task-task-attribution.tentative.html": [
+     "662e17508b26dc671bf4ed25618a3b9ed9b0cac1",
+     [
+      null,
+      {
+       "timeout": "long"
+      }
+     ]
+    ],
+    "navigation-id-mark-measure.tentative.html": [
+     "42795f94a98cd07aee3c13dab7d33bbd2743848e",
+     [
+      null,
+      {
+       "timeout": "long"
+      }
+     ]
+    ],
+    "navigation-id-resource-timing.tentative.html": [
+     "1ec906ebbbba4a8118f746ac94c52aa399556f05",
      [
       null,
       {
@@ -500463,6 +500961,15 @@
       {}
      ]
     ],
+    "link-header-modulepreload.html": [
+     "fd759f6251f2073f9c0015f6b4df692951520ded",
+     [
+      null,
+      {
+       "timeout": "long"
+      }
+     ]
+    ],
     "link-header-on-subresource.html": [
      "418e8a63a7989794e6774ddca7e987bb594c7396",
      [
@@ -500694,7 +501201,7 @@
      ]
     ],
     "subresource-integrity.html": [
-     "0d88aba5223f8854022387b0ce867f4e420810f8",
+     "58f59126edb566e65dd25274b8d713dff449ba85",
      [
       null,
       {}
@@ -522730,7 +523237,7 @@
       ]
      ],
      "restriction-notification.https.html": [
-      "e9d3ba22a5908912302674ba7373a8aa3d1f623b",
+      "205d020ccb88fa0db498f80275384984e96e8783",
       [
        null,
        {
@@ -528217,14 +528724,14 @@
    },
    "subapps": {
     "add-error.tentative.https.html": [
-     "b7d339a90c38ef12cf0ef8794a66027a97116448",
+     "1ae3d0d7affba720bc1546692b8ff7ed59f7d2d5",
      [
       null,
       {}
      ]
     ],
     "add-success.tentative.https.html": [
-     "2463d3c2fdf7b1b67e52a487186a8e8328df12a4",
+     "1f347fd222f05db55b89a4fa73c8f434ea3749c8",
      [
       null,
       {}
@@ -535718,6 +536225,15 @@
       }
      ]
     ],
+    "page-and-offset-in-iframe.html": [
+     "086c816956e8f33929e9e0c3249c9d0555a6e565",
+     [
+      null,
+      {
+       "testdriver": true
+      }
+     ]
+    ],
     "resize-event-order.html": [
      "41a13728bc3ff61cfc32bb02839eab5a11d1d33b",
      [
@@ -535728,7 +536244,7 @@
      ]
     ],
     "scroll-event-order.html": [
-     "5ab5e0747a67bbc82e3620da5cafd1813277245c",
+     "da5b77c0e26a3950dfd1e4d3018dbbbabeb67f9b",
      [
       null,
       {
@@ -566474,6 +566990,13 @@
         {}
        ]
       ],
+      "SharedWorker-constructor.html": [
+       "7909eb5369531243809ba47a4f4ae79e94032937",
+       [
+        null,
+        {}
+       ]
+      ],
       "URLMismatchError.htm": [
        "683d201ad3a0f7bbf8959d731ec20416c347909c",
        [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html
new file mode 100644
index 0000000..007d7a1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS Animations: getComputedStyle().animationTimingFunction with linear(...)</title>
+<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/6533">
+<meta name="assert" content="animation-timing-function: linear(...) parsing tests">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<div id="target"></div>
+<script>
+test_valid_value("animation-timing-function", "linear()");
+test_valid_value("animation-timing-function", "linear(0)");
+test_valid_value("animation-timing-function", "linear(0, 1)");
+test_valid_value("animation-timing-function", "linear(0 0% 100%)");
+test_valid_value("animation-timing-function", "linear(0% 100% 0)", "linear(0 0% 100%)");
+test_valid_value("animation-timing-function", "linear(0 0% 50%, 1 50% 100%)");
+test_valid_value("animation-timing-function", "linear(0, 0.5 25% 75%, 1 100% 100%)");
+test_valid_value("animation-timing-function", "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)");
+
+test_invalid_value("animation-timing-function", "linear(100%)");
+test_invalid_value("animation-timing-function", "linear(0% 1 50%)");
+
+test_computed_value("animation-timing-function", "linear()");
+test_computed_value("animation-timing-function", "linear(0)");
+test_computed_value("animation-timing-function", "linear(0, 1)");
+test_computed_value("animation-timing-function", "linear(0 0% 100%)");
+test_computed_value("animation-timing-function", "linear(0% 100% 0)", "linear(0 0% 100%)");
+test_computed_value("animation-timing-function", "linear(0 0% 50%, 1 50% 100%)");
+test_computed_value("animation-timing-function", "linear(0, 0.5 25% 75%, 1 100% 100%)");
+test_computed_value("animation-timing-function", "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)");
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html b/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html
new file mode 100644
index 0000000..3aa7facf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/svg-with-transform.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1334213">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="columns:2; gap:0; column-fill:auto; width:100px; height:100px; background:red;">
+  <div style="height:100px; background:green;"></div>
+  <svg style="position:relative;">
+    <rect transform="scale(2)" width="25" height="50" fill="green"/>
+  </svg>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html
new file mode 100644
index 0000000..b876399
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-on-focus.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<title>Scroll snap on Element.focus()</title>
+<link rel="help" href="https://drafts.csswg.org/css-scroll-snap/" />
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+div {
+  position: absolute;
+  margin: 0;
+}
+
+#scroller {
+  height: 500px;
+  width: 500px;
+  overflow-y: scroll;
+  scroll-snap-type: y mandatory;
+}
+
+.snap {
+  width: 100%;
+  height: 300px;
+  top: 100px;
+  left: 0;
+  background-color: green;
+  scroll-snap-align: start none;
+}
+
+.no-snap {
+  width: 100%;
+  height: 300px;
+  top: 100px;
+  left: 0;
+  background-color: red;
+}
+
+.area {
+  width: 100%;
+  height: 2000px;
+}
+</style>
+
+<div id="scroller">
+  <div class="area"></div>
+  <div class="snap" style="top: 0px;"></div>
+  <div class="no-snap" style="top: 1000px;" tabindex=-1></div>
+  <div class="snap" style="top: 1200px;"></div>
+</div>
+
+<script>
+test(t => {
+  document.querySelector(".no-snap").focus();
+  assert_equals(scroller.scrollTop, 1200);
+}, "scroll snap should happens on Element.focus()");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html
index 8b1b3cf..a5416119 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent.html
@@ -21,10 +21,24 @@
   const eventWatcher = new EventWatcher(t, document, "error");
   const promise = eventWatcher.wait_for("error").then(e => {
     assert_equals(e.defaultPrevented, false);
+    assert_equals(e.message, "");
+    assert_equals(e.filename, "");
+    assert_equals(e.lineno, 0);
+    assert_equals(e.colno, 0);
+    assert_equals(e.error, undefined);
   });
 
   document.dispatchEvent(new ErrorEvent("error", { cancelable: true }));
 
   return promise;
 }, "error event is normal (return true does not cancel; one arg) on Document, with a synthetic ErrorEvent");
+
+test(() => {
+  const e = new ErrorEvent("error");
+  assert_equals(e.message, "");
+  assert_equals(e.filename, "");
+  assert_equals(e.lineno, 0);
+  assert_equals(e.colno, 0);
+  assert_equals(e.error, undefined);
+}, "Initial values of ErrorEvent members")
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html b/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html
new file mode 100644
index 0000000..fd759f6
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/link-header-modulepreload.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Makes sure that Link headers support modulepreload</title>
+<meta name="timeout" content="long">
+<script src="/common/utils.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/preload/resources/preload_helper.js"></script>
+<body>
+<script>
+    promise_test(async t => {
+        const id = token();
+        const moduleLink = getAbsoluteURL('./resources/module1.js');
+        const params = new URLSearchParams();
+        params.set('link', `<${moduleLink}>;rel=modulepreload`);
+        params.set('type', 'text/html');
+        params.set('file', 'modulepreload-iframe.html')
+        const docURL = getAbsoluteURL(`./resources/echo-preload-header.py?${params.toString()}`);
+        const iframe = document.createElement('iframe');
+        t.add_cleanup(() => iframe.remove());
+        iframe.src = docURL;
+        const messageReceived = new Promise(resolve => window.addEventListener('message', m => {
+            resolve(m.data);
+        }))
+        document.body.appendChild(iframe);
+        const result = await messageReceived;
+        assert_equals(result, 1);
+    }, 'test that a header-preloaded module is loaded and consumed');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html b/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html
new file mode 100644
index 0000000..1d3d21f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/preload/resources/modulepreload-iframe.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<body>
+    <script>
+        const m = new URL('module1.js', location.href).toString();
+        const observer = new PerformanceObserver(l => {
+            const entries = l.getEntriesByName(m);
+            if (entries.length === 1) {
+                import(m).then(() => {
+                    observer.disconnect();
+                    const all = performance.getEntriesByName(m);
+                    window.parent.postMessage(all.length, '*');
+                });
+            }
+        });
+
+        observer.observe({type: 'resource', buffered: true});
+
+
+    </script>
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html
new file mode 100644
index 0000000..ec930a8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/crashtests/cache-response-clone.https.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<meta charset="utf-8">
+<script type="module">
+  const cache = await window.caches.open('cache_name_0')
+  await cache.add("")
+  const resp1 = await cache.match("")
+  const readStream = resp1.body
+  // Cloning will open the stream via NS_AsyncCopy in Gecko
+  resp1.clone()
+  // Give a little bit of time
+  await new Promise(setTimeout)
+  // At this point the previous open operation is about to finish but not yet.
+  // It will finish after the second open operation is made, potentially causing incorrect state.
+  await readStream.getReader().read();
+  document.documentElement.classList.remove('test-wait')
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html b/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html
new file mode 100644
index 0000000..7909eb5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/workers/constructors/SharedWorker/SharedWorker-constructor.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Test SharedWorker constructor functionality.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+test(() => {
+  assert_throws_js(Error,
+                   function() {
+                     new SharedWorker({toString:function(){throw new Error()}})},
+                   'toString exception should be propagated');
+}, 'Test toString propagation exception.');
+
+test(() => {
+  assert_throws_js(TypeError,
+                   function() { new SharedWorker(); },
+                   'invoking SharedWorker constructor without arguments should result ' +
+                   'in an exception.')
+}, 'Test Sharedworker creation with no arguments');
+
+
+test(() => {
+  assert_throws_dom("SyntaxError",
+                    function() { var Sharedworker = new SharedWorker('http://invalid:123$'); },
+                    'Invoking SharedWorker constructor with invalid script URL should ' +
+                    'result in an exception.');
+}, 'Test invalid script URL.');
+
+</script>
diff --git a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html
index c7ca3ac..7f4765d2 100644
--- a/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html
+++ b/third_party/blink/web_tests/fast/forms/calendar-picker/month-picker-scrubby-scrollbar.html
@@ -12,24 +12,40 @@
 <input type=month id=picker>
 
 <script>
-promise_test(async () => {
+const openPickerAndGetThumb = async () => {
   await openPicker(picker);
-
-  async function rAF() {
-    return new Promise(resolve => internals.pagePopupWindow.requestAnimationFrame(resolve));
-  }
-
   const scrubby = internals.pagePopupWindow.global.picker.yearListView_.scrubbyScrollBar;
   const thumb = scrubby.element.querySelector('.scrubby-scroll-thumb');
   const originalTop = thumb.style.top;
   const thumbOffset = cumulativeOffset(thumb);
+  return { thumb, thumbX: thumbOffset[0] + 1, thumbY: thumbOffset[1] + 1, originalTop };
+}
 
-  eventSender.mouseMoveTo(thumbOffset[0] + 1, thumbOffset[1] + 1);
+promise_test(async () => {
+  const {thumb, thumbX, thumbY, originalTop} = await openPickerAndGetThumb();
+
+  eventSender.mouseMoveTo(thumbX, thumbY);
   eventSender.mouseDown();
-  eventSender.mouseMoveTo(thumbOffset[0] + 1, thumbOffset[1] - 15);
+  eventSender.mouseMoveTo(thumbX, thumbY - 15);
   skipAnimation();
   eventSender.mouseUp();
   skipAnimation();
   assert_equals(thumb.style.top, originalTop);
 }, `Verifies that the date picker's scrubby scrollbar returns to its initial state after being clicked and dragged.`);
+
+promise_test(async () => {
+  const {thumb, thumbX, thumbY, originalTop} = await openPickerAndGetThumb();
+
+  eventSender.clearTouchPoints();
+  eventSender.addTouchPoint(thumbX, thumbY);
+  eventSender.touchStart();
+  eventSender.updateTouchPoint(0, thumbX, thumbY - 15);
+  eventSender.touchMove();
+  skipAnimation();
+  eventSender.releaseTouchPoint(0);
+  eventSender.touchEnd();
+  skipAnimation();
+  assert_equals(thumb.style.top, originalTop);
+}, `Verifies that the date picker's scrubby scrollbar returns to its initial state after being touched and dragged.`);
+
 </script>
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt
new file mode 100644
index 0000000..a3d961ad
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/css/css-animations/parsing/animation-timing-function-linear.tentative-expected.txt
@@ -0,0 +1,21 @@
+This is a testharness.js-based test.
+FAIL e.style['animation-timing-function'] = "linear()" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0, 1)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0 0% 100%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0% 100% 0)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0 0% 50%, 1 50% 100%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0, 0.5 25% 75%, 1 100% 100%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+FAIL e.style['animation-timing-function'] = "linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)" should set the property value assert_not_equals: property should be set got disallowed value ""
+PASS e.style['animation-timing-function'] = "linear(100%)" should not set the property value
+PASS e.style['animation-timing-function'] = "linear(0% 1 50%)" should not set the property value
+FAIL Property animation-timing-function value 'linear()' assert_true: 'linear()' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0)' assert_true: 'linear(0)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0, 1)' assert_true: 'linear(0, 1)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0 0% 100%)' assert_true: 'linear(0 0% 100%)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0% 100% 0)' assert_true: 'linear(0% 100% 0)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0 0% 50%, 1 50% 100%)' assert_true: 'linear(0 0% 50%, 1 50% 100%)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0, 0.5 25% 75%, 1 100% 100%)' assert_true: 'linear(0, 0.5 25% 75%, 1 100% 100%)' is a supported value for animation-timing-function. expected true got false
+FAIL Property animation-timing-function value 'linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)' assert_true: 'linear(0, 1.3, 1, 0.92, 1, 0.99, 1, 1.004, 0.998, 1 100% 100%)' is a supported value for animation-timing-function. expected true got false
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt
index d50cca6b..093acf8 100644
--- a/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/semantics/embedded-content/media-elements/src_object_blob-expected.txt
@@ -1,4 +1,4 @@
 This is a testharness.js-based test.
-FAIL HTMLMediaElement.srcObject blob assert_unreached: TypeError: Failed to set the 'srcObject' property on 'HTMLMediaElement': Failed to convert value to 'MediaStream'. Reached unreachable code
+FAIL HTMLMediaElement.srcObject blob assert_unreached: TypeError: Failed to set the 'srcObject' property on 'HTMLMediaElement': The provided value is not of type '(MediaSourceHandle or MediaStream)'. Reached unreachable code
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt b/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt
new file mode 100644
index 0000000..5bfc1594
--- /dev/null
+++ b/third_party/blink/web_tests/platform/generic/external/wpt/html/webappapis/scripting/events/event-handler-processing-algorithm-error/document-synthetic-errorevent-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL error event is normal (return true does not cancel; one arg) on Document, with a synthetic ErrorEvent assert_equals: expected (undefined) undefined but got (object) null
+FAIL Initial values of ErrorEvent members assert_equals: expected (undefined) undefined but got (object) null
+Harness: the test ran to completion.
+
diff --git a/third_party/breakpad/BUILD.gn b/third_party/breakpad/BUILD.gn
index 87ef3e6..2df7b35 100644
--- a/third_party/breakpad/BUILD.gn
+++ b/third_party/breakpad/BUILD.gn
@@ -608,6 +608,9 @@
       "breakpad/src/client/linux/minidump_writer/linux_ptrace_dumper.h",
       "breakpad/src/client/linux/minidump_writer/minidump_writer.cc",
       "breakpad/src/client/linux/minidump_writer/minidump_writer.h",
+      "breakpad/src/client/linux/minidump_writer/pe_file.cc",
+      "breakpad/src/client/linux/minidump_writer/pe_file.h",
+      "breakpad/src/client/linux/minidump_writer/pe_structs.h",
       "breakpad/src/client/linux/minidump_writer/proc_cpuinfo_reader.h",
       "breakpad/src/client/minidump_file_writer-inl.h",
       "breakpad/src/client/minidump_file_writer.cc",
@@ -865,6 +868,8 @@
         "breakpad/src/common/windows/pe_util.h",
         "breakpad/src/common/windows/string_utils-inl.h",
         "breakpad/src/common/windows/string_utils.cc",
+        "breakpad/src/common/windows/sym_upload_v2_protocol.cc",
+        "breakpad/src/common/windows/sym_upload_v2_protocol.h",
         "breakpad/src/common/windows/symbol_collector_client.cc",
         "breakpad/src/common/windows/symbol_collector_client.h",
       ]
diff --git a/third_party/lottie/BUILD.gn b/third_party/lottie/BUILD.gn
index 6e2bb195..3a18ad7 100644
--- a/third_party/lottie/BUILD.gn
+++ b/third_party/lottie/BUILD.gn
@@ -24,7 +24,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "lottie"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":minify" ]
+  public_deps = [ ":minify" ]
   input_files_base_dir = rebase_path(target_gen_dir, root_build_dir)
   input_files = [ "lottie_worker.min.js" ]
   resource_path_prefix = "lottie"
diff --git a/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js b/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js
index 4f998c4..d8e8613 100644
--- a/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js
+++ b/third_party/polymer/v3_0/components-chromium/polymer/polymer_bundled.min.js
@@ -1 +1 @@
-window.JSCompiler_renameProperty=function(prop,obj){return prop};let microtaskCurrHandle=0;let microtaskLastHandle=0;let microtaskCallbacks=[];let microtaskNodeContent=0;let microtaskNode=document.createTextNode("");new window.MutationObserver(microtaskFlush).observe(microtaskNode,{characterData:true});function microtaskFlush(){const len=microtaskCallbacks.length;for(let i=0;i<len;i++){let cb=microtaskCallbacks[i];if(cb){try{cb()}catch(e){setTimeout((()=>{throw e}))}}}microtaskCallbacks.splice(0,len);microtaskLastHandle+=len}const timeOut={after(delay){return{run(fn){return window.setTimeout(fn,delay)},cancel(handle){window.clearTimeout(handle)}}},run(fn,delay){return window.setTimeout(fn,delay)},cancel(handle){window.clearTimeout(handle)}};const animationFrame={run(fn){return window.requestAnimationFrame(fn)},cancel(handle){window.cancelAnimationFrame(handle)}};const idlePeriod={run(fn){return window.requestIdleCallback?window.requestIdleCallback(fn):window.setTimeout(fn,16)},cancel(handle){window.cancelIdleCallback?window.cancelIdleCallback(handle):window.clearTimeout(handle)}};const microTask={run(callback){microtaskNode.textContent=microtaskNodeContent++;microtaskCallbacks.push(callback);return microtaskCurrHandle++},cancel(handle){const idx=handle-microtaskLastHandle;if(idx>=0){if(!microtaskCallbacks[idx]){throw new Error("invalid async handle: "+handle)}microtaskCallbacks[idx]=null}}};let dedupeId$1=0;const dedupingMixin=function(mixin){let mixinApplications=mixin.__mixinApplications;if(!mixinApplications){mixinApplications=new WeakMap;mixin.__mixinApplications=mixinApplications}let mixinDedupeId=dedupeId$1++;function dedupingMixin(base){let baseSet=base.__mixinSet;if(baseSet&&baseSet[mixinDedupeId]){return base}let map=mixinApplications;let extended=map.get(base);if(!extended){extended=mixin(base);map.set(base,extended)}let mixinSet=Object.create(extended.__mixinSet||baseSet||null);mixinSet[mixinDedupeId]=true;extended.__mixinSet=mixinSet;return extended}return dedupingMixin};class Debouncer{constructor(){this._asyncModule=null;this._callback=null;this._timer=null}setConfig(asyncModule,callback){this._asyncModule=asyncModule;this._callback=callback;this._timer=this._asyncModule.run((()=>{this._timer=null;debouncerQueue.delete(this);this._callback()}))}cancel(){if(this.isActive()){this._cancelAsync();debouncerQueue.delete(this)}}_cancelAsync(){if(this.isActive()){this._asyncModule.cancel(this._timer);this._timer=null}}flush(){if(this.isActive()){this.cancel();this._callback()}}isActive(){return this._timer!=null}static debounce(debouncer,asyncModule,callback){if(debouncer instanceof Debouncer){debouncer._cancelAsync()}else{debouncer=new Debouncer}debouncer.setConfig(asyncModule,callback);return debouncer}}let debouncerQueue=new Set;const enqueueDebouncer=function(debouncer){debouncerQueue.add(debouncer)};const flushDebouncers=function(){const didFlush=Boolean(debouncerQueue.size);debouncerQueue.forEach((debouncer=>{try{debouncer.flush()}catch(e){setTimeout((()=>{throw e}))}}));return didFlush};let CSS_URL_RX=/(url\()([^)]*)(\))/g;let ABS_URL=/(^\/)|(^#)|(^[\w-\d]*:)/;let workingURL;let resolveDoc;function resolveUrl(url,baseURI){if(url&&ABS_URL.test(url)){return url}if(workingURL===undefined){workingURL=false;try{const u=new URL("b","http://a");u.pathname="c%20d";workingURL=u.href==="http://a/c%20d"}catch(e){}}if(!baseURI){baseURI=document.baseURI||window.location.href}if(workingURL){return new URL(url,baseURI).href}if(!resolveDoc){resolveDoc=document.implementation.createHTMLDocument("temp");resolveDoc.base=resolveDoc.createElement("base");resolveDoc.head.appendChild(resolveDoc.base);resolveDoc.anchor=resolveDoc.createElement("a");resolveDoc.body.appendChild(resolveDoc.anchor)}resolveDoc.base.href=baseURI;resolveDoc.anchor.href=url;return resolveDoc.anchor.href||url}function resolveCss(cssText,baseURI){return cssText.replace(CSS_URL_RX,(function(m,pre,url,post){return pre+"'"+resolveUrl(url.replace(/["']/g,""),baseURI)+"'"+post}))}function pathFromUrl(url){return url.substring(0,url.lastIndexOf("/")+1)}const useShadow=!window.ShadyDOM;Boolean(!window.ShadyCSS||window.ShadyCSS.nativeCss);let rootPath=pathFromUrl(document.baseURI||window.location.href);let sanitizeDOMValue=window.Polymer&&window.Polymer.sanitizeDOMValue||undefined;let passiveTouchGestures=false;let strictTemplatePolicy=false;const wrap=window["ShadyDOM"]&&window["ShadyDOM"]["noPatch"]&&window["ShadyDOM"]["wrap"]?window["ShadyDOM"]["wrap"]:n=>n;let HAS_NATIVE_TA=typeof document.head.style.touchAction==="string";let GESTURE_KEY="__polymerGestures";let HANDLED_OBJ="__polymerGesturesHandled";let TOUCH_ACTION="__polymerGesturesTouchAction";let TAP_DISTANCE=25;let TRACK_DISTANCE=5;let TRACK_LENGTH=2;let MOUSE_TIMEOUT=2500;let MOUSE_EVENTS=["mousedown","mousemove","mouseup","click"];let MOUSE_WHICH_TO_BUTTONS=[0,1,4,2];let MOUSE_HAS_BUTTONS=function(){try{return new MouseEvent("test",{buttons:1}).buttons===1}catch(e){return false}}();function isMouseEvent(name){return MOUSE_EVENTS.indexOf(name)>-1}let SUPPORTS_PASSIVE=false;(function(){try{let opts=Object.defineProperty({},"passive",{get(){SUPPORTS_PASSIVE=true}});window.addEventListener("test",null,opts);window.removeEventListener("test",null,opts)}catch(e){}})();function PASSIVE_TOUCH(eventName){if(isMouseEvent(eventName)||eventName==="touchend"){return}if(HAS_NATIVE_TA&&SUPPORTS_PASSIVE&&passiveTouchGestures){return{passive:true}}else{return}}let IS_TOUCH_ONLY=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);const clickedLabels=[];const labellable={button:true,input:true,keygen:true,meter:true,output:true,textarea:true,progress:true,select:true};const canBeDisabled={button:true,command:true,fieldset:true,input:true,keygen:true,optgroup:true,option:true,select:true,textarea:true};function canBeLabelled(el){return labellable[el.localName]||false}function matchingLabels(el){let labels=Array.prototype.slice.call(el.labels||[]);if(!labels.length){labels=[];let root=el.getRootNode();if(el.id){let matching=root.querySelectorAll(`label[for = ${el.id}]`);for(let i=0;i<matching.length;i++){labels.push(matching[i])}}}return labels}let mouseCanceller=function(mouseEvent){let sc=mouseEvent.sourceCapabilities;if(sc&&!sc.firesTouchEvents){return}mouseEvent[HANDLED_OBJ]={skip:true};if(mouseEvent.type==="click"){let clickFromLabel=false;let path=getComposedPath(mouseEvent);for(let i=0;i<path.length;i++){if(path[i].nodeType===Node.ELEMENT_NODE){if(path[i].localName==="label"){clickedLabels.push(path[i])}else if(canBeLabelled(path[i])){let ownerLabels=matchingLabels(path[i]);for(let j=0;j<ownerLabels.length;j++){clickFromLabel=clickFromLabel||clickedLabels.indexOf(ownerLabels[j])>-1}}}if(path[i]===POINTERSTATE.mouse.target){return}}if(clickFromLabel){return}mouseEvent.preventDefault();mouseEvent.stopPropagation()}};function setupTeardownMouseCanceller(setup){let events=IS_TOUCH_ONLY?["click"]:MOUSE_EVENTS;for(let i=0,en;i<events.length;i++){en=events[i];if(setup){clickedLabels.length=0;document.addEventListener(en,mouseCanceller,true)}else{document.removeEventListener(en,mouseCanceller,true)}}}function ignoreMouse(e){if(!POINTERSTATE.mouse.mouseIgnoreJob){setupTeardownMouseCanceller(true)}let unset=function(){setupTeardownMouseCanceller();POINTERSTATE.mouse.target=null;POINTERSTATE.mouse.mouseIgnoreJob=null};POINTERSTATE.mouse.target=getComposedPath(e)[0];POINTERSTATE.mouse.mouseIgnoreJob=Debouncer.debounce(POINTERSTATE.mouse.mouseIgnoreJob,timeOut.after(MOUSE_TIMEOUT),unset)}function hasLeftMouseButton(ev){let type=ev.type;if(!isMouseEvent(type)){return false}if(type==="mousemove"){let buttons=ev.buttons===undefined?1:ev.buttons;if(ev instanceof window.MouseEvent&&!MOUSE_HAS_BUTTONS){buttons=MOUSE_WHICH_TO_BUTTONS[ev.which]||0}return Boolean(buttons&1)}else{let button=ev.button===undefined?0:ev.button;return button===0}}function isSyntheticClick(ev){if(ev.type==="click"){if(ev.detail===0){return true}let t=_findOriginalTarget(ev);if(!t.nodeType||t.nodeType!==Node.ELEMENT_NODE){return true}let bcr=t.getBoundingClientRect();let x=ev.pageX,y=ev.pageY;return!(x>=bcr.left&&x<=bcr.right&&(y>=bcr.top&&y<=bcr.bottom))}return false}let POINTERSTATE={mouse:{target:null,mouseIgnoreJob:null},touch:{x:0,y:0,id:-1,scrollDecided:false}};function firstTouchAction(ev){let ta="auto";let path=getComposedPath(ev);for(let i=0,n;i<path.length;i++){n=path[i];if(n[TOUCH_ACTION]){ta=n[TOUCH_ACTION];break}}return ta}function trackDocument(stateObj,movefn,upfn){stateObj.movefn=movefn;stateObj.upfn=upfn;document.addEventListener("mousemove",movefn);document.addEventListener("mouseup",upfn)}function untrackDocument(stateObj){document.removeEventListener("mousemove",stateObj.movefn);document.removeEventListener("mouseup",stateObj.upfn);stateObj.movefn=null;stateObj.upfn=null}document.addEventListener("touchend",ignoreMouse,SUPPORTS_PASSIVE?{passive:true}:false);const getComposedPath=window.ShadyDOM&&window.ShadyDOM.noPatch?window.ShadyDOM.composedPath:event=>event.composedPath&&event.composedPath()||[];const gestures={};const recognizers=[];function deepTargetFind(x,y){let node=document.elementFromPoint(x,y);let next=node;while(next&&next.shadowRoot&&!window.ShadyDOM){let oldNext=next;next=next.shadowRoot.elementFromPoint(x,y);if(oldNext===next){break}if(next){node=next}}return node}function _findOriginalTarget(ev){const path=getComposedPath(ev);return path.length>0?path[0]:ev.target}function _handleNative(ev){let handled;let type=ev.type;let node=ev.currentTarget;let gobj=node[GESTURE_KEY];if(!gobj){return}let gs=gobj[type];if(!gs){return}if(!ev[HANDLED_OBJ]){ev[HANDLED_OBJ]={};if(type.slice(0,5)==="touch"){ev=ev;let t=ev.changedTouches[0];if(type==="touchstart"){if(ev.touches.length===1){POINTERSTATE.touch.id=t.identifier}}if(POINTERSTATE.touch.id!==t.identifier){return}if(!HAS_NATIVE_TA){if(type==="touchstart"||type==="touchmove"){_handleTouchAction(ev)}}}}handled=ev[HANDLED_OBJ];if(handled.skip){return}for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){if(r.flow&&r.flow.start.indexOf(ev.type)>-1&&r.reset){r.reset()}}}for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];if(gs[r.name]&&!handled[r.name]){handled[r.name]=true;r[type](ev)}}}function _handleTouchAction(ev){let t=ev.changedTouches[0];let type=ev.type;if(type==="touchstart"){POINTERSTATE.touch.x=t.clientX;POINTERSTATE.touch.y=t.clientY;POINTERSTATE.touch.scrollDecided=false}else if(type==="touchmove"){if(POINTERSTATE.touch.scrollDecided){return}POINTERSTATE.touch.scrollDecided=true;let ta=firstTouchAction(ev);let shouldPrevent=false;let dx=Math.abs(POINTERSTATE.touch.x-t.clientX);let dy=Math.abs(POINTERSTATE.touch.y-t.clientY);if(!ev.cancelable);else if(ta==="none"){shouldPrevent=true}else if(ta==="pan-x"){shouldPrevent=dy>dx}else if(ta==="pan-y"){shouldPrevent=dx>dy}if(shouldPrevent){ev.preventDefault()}else{prevent("track")}}}function addListener(node,evType,handler){if(gestures[evType]){_add(node,evType,handler);return true}return false}function removeListener(node,evType,handler){if(gestures[evType]){_remove(node,evType,handler);return true}return false}function _add(node,evType,handler){let recognizer=gestures[evType];let deps=recognizer.deps;let name=recognizer.name;let gobj=node[GESTURE_KEY];if(!gobj){node[GESTURE_KEY]=gobj={}}for(let i=0,dep,gd;i<deps.length;i++){dep=deps[i];if(IS_TOUCH_ONLY&&isMouseEvent(dep)&&dep!=="click"){continue}gd=gobj[dep];if(!gd){gobj[dep]=gd={_count:0}}if(gd._count===0){node.addEventListener(dep,_handleNative,PASSIVE_TOUCH(dep))}gd[name]=(gd[name]||0)+1;gd._count=(gd._count||0)+1}node.addEventListener(evType,handler);if(recognizer.touchAction){setTouchAction(node,recognizer.touchAction)}}function _remove(node,evType,handler){let recognizer=gestures[evType];let deps=recognizer.deps;let name=recognizer.name;let gobj=node[GESTURE_KEY];if(gobj){for(let i=0,dep,gd;i<deps.length;i++){dep=deps[i];gd=gobj[dep];if(gd&&gd[name]){gd[name]=(gd[name]||1)-1;gd._count=(gd._count||1)-1;if(gd._count===0){node.removeEventListener(dep,_handleNative,PASSIVE_TOUCH(dep))}}}}node.removeEventListener(evType,handler)}function register$1(recog){recognizers.push(recog);for(let i=0;i<recog.emits.length;i++){gestures[recog.emits[i]]=recog}}function _findRecognizerByEvent(evName){for(let i=0,r;i<recognizers.length;i++){r=recognizers[i];for(let j=0,n;j<r.emits.length;j++){n=r.emits[j];if(n===evName){return r}}}return null}function setTouchAction(node,value){if(HAS_NATIVE_TA&&node instanceof HTMLElement){microTask.run((()=>{node.style.touchAction=value}))}node[TOUCH_ACTION]=value}function _fire(target,type,detail){let ev=new Event(type,{bubbles:true,cancelable:true,composed:true});ev.detail=detail;wrap(target).dispatchEvent(ev);if(ev.defaultPrevented){let preventer=detail.preventer||detail.sourceEvent;if(preventer&&preventer.preventDefault){preventer.preventDefault()}}}function prevent(evName){let recognizer=_findRecognizerByEvent(evName);if(recognizer.info){recognizer.info.prevent=true}}function resetMouseCanceller(){if(POINTERSTATE.mouse.mouseIgnoreJob){POINTERSTATE.mouse.mouseIgnoreJob.flush()}}register$1({name:"downup",deps:["mousedown","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["down","up"],info:{movefn:null,upfn:null},reset:function(){untrackDocument(this.info)},mousedown:function(e){if(!hasLeftMouseButton(e)){return}let t=_findOriginalTarget(e);let self=this;let movefn=function movefn(e){if(!hasLeftMouseButton(e)){downupFire("up",t,e);untrackDocument(self.info)}};let upfn=function upfn(e){if(hasLeftMouseButton(e)){downupFire("up",t,e)}untrackDocument(self.info)};trackDocument(this.info,movefn,upfn);downupFire("down",t,e)},touchstart:function(e){downupFire("down",_findOriginalTarget(e),e.changedTouches[0],e)},touchend:function(e){downupFire("up",_findOriginalTarget(e),e.changedTouches[0],e)}});function downupFire(type,target,event,preventer){if(!target){return}_fire(target,type,{x:event.clientX,y:event.clientY,sourceEvent:event,preventer:preventer,prevent:function(e){return prevent(e)}})}register$1({name:"track",touchAction:"none",deps:["mousedown","touchstart","touchmove","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["track"],info:{x:0,y:0,state:"start",started:false,moves:[],addMove:function(move){if(this.moves.length>TRACK_LENGTH){this.moves.shift()}this.moves.push(move)},movefn:null,upfn:null,prevent:false},reset:function(){this.info.state="start";this.info.started=false;this.info.moves=[];this.info.x=0;this.info.y=0;this.info.prevent=false;untrackDocument(this.info)},mousedown:function(e){if(!hasLeftMouseButton(e)){return}let t=_findOriginalTarget(e);let self=this;let movefn=function movefn(e){let x=e.clientX,y=e.clientY;if(trackHasMovedEnough(self.info,x,y)){self.info.state=self.info.started?e.type==="mouseup"?"end":"track":"start";if(self.info.state==="start"){prevent("tap")}self.info.addMove({x:x,y:y});if(!hasLeftMouseButton(e)){self.info.state="end";untrackDocument(self.info)}if(t){trackFire(self.info,t,e)}self.info.started=true}};let upfn=function upfn(e){if(self.info.started){movefn(e)}untrackDocument(self.info)};trackDocument(this.info,movefn,upfn);this.info.x=e.clientX;this.info.y=e.clientY},touchstart:function(e){let ct=e.changedTouches[0];this.info.x=ct.clientX;this.info.y=ct.clientY},touchmove:function(e){let t=_findOriginalTarget(e);let ct=e.changedTouches[0];let x=ct.clientX,y=ct.clientY;if(trackHasMovedEnough(this.info,x,y)){if(this.info.state==="start"){prevent("tap")}this.info.addMove({x:x,y:y});trackFire(this.info,t,ct);this.info.state="track";this.info.started=true}},touchend:function(e){let t=_findOriginalTarget(e);let ct=e.changedTouches[0];if(this.info.started){this.info.state="end";this.info.addMove({x:ct.clientX,y:ct.clientY});trackFire(this.info,t,ct)}}});function trackHasMovedEnough(info,x,y){if(info.prevent){return false}if(info.started){return true}let dx=Math.abs(info.x-x);let dy=Math.abs(info.y-y);return dx>=TRACK_DISTANCE||dy>=TRACK_DISTANCE}function trackFire(info,target,touch){if(!target){return}let secondlast=info.moves[info.moves.length-2];let lastmove=info.moves[info.moves.length-1];let dx=lastmove.x-info.x;let dy=lastmove.y-info.y;let ddx,ddy=0;if(secondlast){ddx=lastmove.x-secondlast.x;ddy=lastmove.y-secondlast.y}_fire(target,"track",{state:info.state,x:touch.clientX,y:touch.clientY,dx:dx,dy:dy,ddx:ddx,ddy:ddy,sourceEvent:touch,hover:function(){return deepTargetFind(touch.clientX,touch.clientY)}})}register$1({name:"tap",deps:["mousedown","click","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["click","touchend"]},emits:["tap"],info:{x:NaN,y:NaN,prevent:false},reset:function(){this.info.x=NaN;this.info.y=NaN;this.info.prevent=false},mousedown:function(e){if(hasLeftMouseButton(e)){this.info.x=e.clientX;this.info.y=e.clientY}},click:function(e){if(hasLeftMouseButton(e)){trackForward(this.info,e)}},touchstart:function(e){const touch=e.changedTouches[0];this.info.x=touch.clientX;this.info.y=touch.clientY},touchend:function(e){trackForward(this.info,e.changedTouches[0],e)}});function trackForward(info,e,preventer){let dx=Math.abs(e.clientX-info.x);let dy=Math.abs(e.clientY-info.y);let t=_findOriginalTarget(preventer||e);if(!t||canBeDisabled[t.localName]&&t.hasAttribute("disabled")){return}if(isNaN(dx)||isNaN(dy)||dx<=TAP_DISTANCE&&dy<=TAP_DISTANCE||isSyntheticClick(e)){if(!info.prevent){_fire(t,"tap",{x:e.clientX,y:e.clientY,sourceEvent:e,preventer:preventer})}}}const findOriginalTarget=_findOriginalTarget;const add=addListener;const remove=removeListener;var gestures$1=Object.freeze({__proto__:null,gestures:gestures,recognizers:recognizers,deepTargetFind:deepTargetFind,addListener:addListener,removeListener:removeListener,register:register$1,setTouchAction:setTouchAction,prevent:prevent,resetMouseCanceller:resetMouseCanceller,findOriginalTarget:findOriginalTarget,add:add,remove:remove});let modules={};let lcModules={};function setModule(id,module){modules[id]=lcModules[id.toLowerCase()]=module}function findModule(id){return modules[id]||lcModules[id.toLowerCase()]}function styleOutsideTemplateCheck(inst){if(inst.querySelector("style")){console.warn("dom-module %s has style outside template",inst.id)}}class DomModule extends HTMLElement{static get observedAttributes(){return["id"]}static import(id,selector){if(id){let m=findModule(id);if(m&&selector){return m.querySelector(selector)}return m}return null}attributeChangedCallback(name,old,value,namespace){if(old!==value){this.register()}}get assetpath(){if(!this.__assetpath){const owner=window.HTMLImports&&HTMLImports.importForElement?HTMLImports.importForElement(this)||document:this.ownerDocument;const url=resolveUrl(this.getAttribute("assetpath")||"",owner.baseURI);this.__assetpath=pathFromUrl(url)}return this.__assetpath}register(id){id=id||this.id;if(id){this.id=id;setModule(id,this);styleOutsideTemplateCheck(this)}}}DomModule.prototype["modules"]=modules;customElements.define("dom-module",DomModule);const MODULE_STYLE_LINK_SELECTOR="link[rel=import][type~=css]";const INCLUDE_ATTR="include";const SHADY_UNSCOPED_ATTR="shady-unscoped";function importModule(moduleId){return DomModule.import(moduleId)}function styleForImport(importDoc){let container=importDoc.body?importDoc.body:importDoc;const importCss=resolveCss(container.textContent,importDoc.baseURI);const style=document.createElement("style");style.textContent=importCss;return style}function stylesFromModules(moduleIds){const modules=moduleIds.trim().split(/\s+/);const styles=[];for(let i=0;i<modules.length;i++){styles.push(...stylesFromModule(modules[i]))}return styles}function stylesFromModule(moduleId){const m=importModule(moduleId);if(!m){console.warn("Could not find style data in module named",moduleId);return[]}if(m._styles===undefined){const styles=[];styles.push(..._stylesFromModuleImports(m));const template=m.querySelector("template");if(template){styles.push(...stylesFromTemplate(template,m.assetpath))}m._styles=styles}return m._styles}function stylesFromTemplate(template,baseURI){if(!template._styles){const styles=[];const e$=template.content.querySelectorAll("style");for(let i=0;i<e$.length;i++){let e=e$[i];let include=e.getAttribute(INCLUDE_ATTR);if(include){styles.push(...stylesFromModules(include).filter((function(item,index,self){return self.indexOf(item)===index})))}if(baseURI){e.textContent=resolveCss(e.textContent,baseURI)}styles.push(e)}template._styles=styles}return template._styles}function stylesFromModuleImports(moduleId){let m=importModule(moduleId);return m?_stylesFromModuleImports(m):[]}function _stylesFromModuleImports(module){const styles=[];const p$=module.querySelectorAll(MODULE_STYLE_LINK_SELECTOR);for(let i=0;i<p$.length;i++){let p=p$[i];if(p.import){const importDoc=p.import;const unscoped=p.hasAttribute(SHADY_UNSCOPED_ATTR);if(unscoped&&!importDoc._unscopedStyle){const style=styleForImport(importDoc);style.setAttribute(SHADY_UNSCOPED_ATTR,"");importDoc._unscopedStyle=style}else if(!importDoc._style){importDoc._style=styleForImport(importDoc)}styles.push(unscoped?importDoc._unscopedStyle:importDoc._style)}}return styles}function cssFromModules(moduleIds){let modules=moduleIds.trim().split(/\s+/);let cssText="";for(let i=0;i<modules.length;i++){cssText+=cssFromModule(modules[i])}return cssText}function cssFromModule(moduleId){let m=importModule(moduleId);if(m&&m._cssText===undefined){let cssText=_cssFromModuleImports(m);let t=m.querySelector("template");if(t){cssText+=cssFromTemplate(t,m.assetpath)}m._cssText=cssText||null}if(!m){console.warn("Could not find style data in module named",moduleId)}return m&&m._cssText||""}function cssFromTemplate(template,baseURI){let cssText="";const e$=stylesFromTemplate(template,baseURI);for(let i=0;i<e$.length;i++){let e=e$[i];if(e.parentNode){e.parentNode.removeChild(e)}cssText+=e.textContent}return cssText}function _cssFromModuleImports(module){let cssText="";let styles=_stylesFromModuleImports(module);for(let i=0;i<styles.length;i++){cssText+=styles[i].textContent}return cssText}function isPath(path){return path.indexOf(".")>=0}function root(path){let dotIndex=path.indexOf(".");if(dotIndex===-1){return path}return path.slice(0,dotIndex)}function isAncestor(base,path){return base.indexOf(path+".")===0}function isDescendant(base,path){return path.indexOf(base+".")===0}function translate(base,newBase,path){return newBase+path.slice(base.length)}function matches(base,path){return base===path||isAncestor(base,path)||isDescendant(base,path)}function normalize(path){if(Array.isArray(path)){let parts=[];for(let i=0;i<path.length;i++){let args=path[i].toString().split(".");for(let j=0;j<args.length;j++){parts.push(args[j])}}return parts.join(".")}else{return path}}function split(path){if(Array.isArray(path)){return normalize(path).split(".")}return path.toString().split(".")}function get(root,path,info){let prop=root;let parts=split(path);for(let i=0;i<parts.length;i++){if(!prop){return}let part=parts[i];prop=prop[part]}if(info){info.path=parts.join(".")}return prop}function set(root,path,value){let prop=root;let parts=split(path);let last=parts[parts.length-1];if(parts.length>1){for(let i=0;i<parts.length-1;i++){let part=parts[i];prop=prop[part];if(!prop){return}}prop[last]=value}else{prop[path]=value}return parts.join(".")}const caseMap={};const DASH_TO_CAMEL=/-[a-z]/g;const CAMEL_TO_DASH=/([A-Z])/g;function dashToCamelCase(dash){return caseMap[dash]||(caseMap[dash]=dash.indexOf("-")<0?dash:dash.replace(DASH_TO_CAMEL,(m=>m[1].toUpperCase())))}function camelToDashCase(camel){return caseMap[camel]||(caseMap[camel]=camel.replace(CAMEL_TO_DASH,"-$1").toLowerCase())}const microtask=microTask;const PropertiesChanged=dedupingMixin((superClass=>{class PropertiesChanged extends superClass{static createProperties(props){const proto=this.prototype;for(let prop in props){if(!(prop in proto)){proto._createPropertyAccessor(prop)}}}static attributeNameForProperty(property){return property.toLowerCase()}static typeForProperty(name){}_createPropertyAccessor(property,readOnly){this._addPropertyToAttributeMap(property);if(!this.hasOwnProperty("__dataHasAccessor")){this.__dataHasAccessor=Object.assign({},this.__dataHasAccessor)}if(!this.__dataHasAccessor[property]){this.__dataHasAccessor[property]=true;this._definePropertyAccessor(property,readOnly)}}_addPropertyToAttributeMap(property){if(!this.hasOwnProperty("__dataAttributes")){this.__dataAttributes=Object.assign({},this.__dataAttributes)}if(!this.__dataAttributes[property]){const attr=this.constructor.attributeNameForProperty(property);this.__dataAttributes[attr]=property}}_definePropertyAccessor(property,readOnly){Object.defineProperty(this,property,{get(){return this._getProperty(property)},set:readOnly?function(){}:function(value){this._setProperty(property,value)}})}constructor(){super();this.__dataEnabled=false;this.__dataReady=false;this.__dataInvalid=false;this.__data={};this.__dataPending=null;this.__dataOld=null;this.__dataInstanceProps=null;this.__serializing=false;this._initializeProperties()}ready(){this.__dataReady=true;this._flushProperties()}_initializeProperties(){for(let p in this.__dataHasAccessor){if(this.hasOwnProperty(p)){this.__dataInstanceProps=this.__dataInstanceProps||{};this.__dataInstanceProps[p]=this[p];delete this[p]}}}_initializeInstanceProperties(props){Object.assign(this,props)}_setProperty(property,value){if(this._setPendingProperty(property,value)){this._invalidateProperties()}}_getProperty(property){return this.__data[property]}_setPendingProperty(property,value,ext){let old=this.__data[property];let changed=this._shouldPropertyChange(property,value,old);if(changed){if(!this.__dataPending){this.__dataPending={};this.__dataOld={}}if(this.__dataOld&&!(property in this.__dataOld)){this.__dataOld[property]=old}this.__data[property]=value;this.__dataPending[property]=value}return changed}_invalidateProperties(){if(!this.__dataInvalid&&this.__dataReady){this.__dataInvalid=true;microtask.run((()=>{if(this.__dataInvalid){this.__dataInvalid=false;this._flushProperties()}}))}}_enableProperties(){if(!this.__dataEnabled){this.__dataEnabled=true;if(this.__dataInstanceProps){this._initializeInstanceProperties(this.__dataInstanceProps);this.__dataInstanceProps=null}this.ready()}}_flushProperties(){const props=this.__data;const changedProps=this.__dataPending;const old=this.__dataOld;if(this._shouldPropertiesChange(props,changedProps,old)){this.__dataPending=null;this.__dataOld=null;this._propertiesChanged(props,changedProps,old)}}_shouldPropertiesChange(currentProps,changedProps,oldProps){return Boolean(changedProps)}_propertiesChanged(currentProps,changedProps,oldProps){}_shouldPropertyChange(property,value,old){return old!==value&&(old===old||value===value)}attributeChangedCallback(name,old,value,namespace){if(old!==value){this._attributeToProperty(name,value)}if(super.attributeChangedCallback){super.attributeChangedCallback(name,old,value,namespace)}}_attributeToProperty(attribute,value,type){if(!this.__serializing){const map=this.__dataAttributes;const property=map&&map[attribute]||attribute;this[property]=this._deserializeValue(value,type||this.constructor.typeForProperty(property))}}_propertyToAttribute(property,attribute,value){this.__serializing=true;value=arguments.length<3?this[property]:value;this._valueToNodeAttribute(this,value,attribute||this.constructor.attributeNameForProperty(property));this.__serializing=false}_valueToNodeAttribute(node,value,attribute){const str=this._serializeValue(value);if(str===undefined){node.removeAttribute(attribute)}else{if(attribute==="class"||attribute==="name"||attribute==="slot"){node=wrap(node)}node.setAttribute(attribute,str)}}_serializeValue(value){switch(typeof value){case"boolean":return value?"":undefined;default:return value!=null?value.toString():undefined}}_deserializeValue(value,type){switch(type){case Boolean:return value!==null;case Number:return Number(value);default:return value}}}return PropertiesChanged}));const nativeProperties={};let proto=HTMLElement.prototype;while(proto){let props=Object.getOwnPropertyNames(proto);for(let i=0;i<props.length;i++){nativeProperties[props[i]]=true}proto=Object.getPrototypeOf(proto)}function saveAccessorValue(model,property){if(!nativeProperties[property]){let value=model[property];if(value!==undefined){if(model.__data){model._setPendingProperty(property,value)}else{if(!model.__dataProto){model.__dataProto={}}else if(!model.hasOwnProperty(JSCompiler_renameProperty("__dataProto",model))){model.__dataProto=Object.create(model.__dataProto)}model.__dataProto[property]=value}}}}const PropertyAccessors=dedupingMixin((superClass=>{const base=PropertiesChanged(superClass);class PropertyAccessors extends base{static createPropertiesForAttributes(){let a$=this.observedAttributes;for(let i=0;i<a$.length;i++){this.prototype._createPropertyAccessor(dashToCamelCase(a$[i]))}}static attributeNameForProperty(property){return camelToDashCase(property)}_initializeProperties(){if(this.__dataProto){this._initializeProtoProperties(this.__dataProto);this.__dataProto=null}super._initializeProperties()}_initializeProtoProperties(props){for(let p in props){this._setProperty(p,props[p])}}_ensureAttribute(attribute,value){const el=this;if(!el.hasAttribute(attribute)){this._valueToNodeAttribute(el,value,attribute)}}_serializeValue(value){switch(typeof value){case"object":if(value instanceof Date){return value.toString()}else if(value){try{return JSON.stringify(value)}catch(x){return""}}default:return super._serializeValue(value)}}_deserializeValue(value,type){let outValue;switch(type){case Object:try{outValue=JSON.parse(value)}catch(x){outValue=value}break;case Array:try{outValue=JSON.parse(value)}catch(x){outValue=null;console.warn(`Polymer::Attributes: couldn't decode Array as JSON: ${value}`)}break;case Date:outValue=isNaN(value)?String(value):Number(value);outValue=new Date(outValue);break;default:outValue=super._deserializeValue(value,type);break}return outValue}_definePropertyAccessor(property,readOnly){saveAccessorValue(this,property);super._definePropertyAccessor(property,readOnly)}_hasAccessor(property){return this.__dataHasAccessor&&this.__dataHasAccessor[property]}_isPropertyPending(prop){return Boolean(this.__dataPending&&prop in this.__dataPending)}}return PropertyAccessors}));const walker=document.createTreeWalker(document,NodeFilter.SHOW_ALL,null,false);const templateExtensions={"dom-if":true,"dom-repeat":true};function wrapTemplateExtension(node){let is=node.getAttribute("is");if(is&&templateExtensions[is]){let t=node;t.removeAttribute("is");node=t.ownerDocument.createElement(is);t.parentNode.replaceChild(node,t);node.appendChild(t);while(t.attributes.length){node.setAttribute(t.attributes[0].name,t.attributes[0].value);t.removeAttribute(t.attributes[0].name)}}return node}function findTemplateNode(root,nodeInfo){let parent=nodeInfo.parentInfo&&findTemplateNode(root,nodeInfo.parentInfo);if(parent){walker.currentNode=parent;for(let n=walker.firstChild(),i=0;n;n=walker.nextSibling()){if(nodeInfo.parentIndex===i++){return n}}}else{return root}}function applyIdToMap(inst,map,node,nodeInfo){if(nodeInfo.id){map[nodeInfo.id]=node}}function applyEventListener(inst,node,nodeInfo){if(nodeInfo.events&&nodeInfo.events.length){for(let j=0,e$=nodeInfo.events,e;j<e$.length&&(e=e$[j]);j++){inst._addMethodEventListenerToNode(node,e.name,e.value,inst)}}}function applyTemplateContent(inst,node,nodeInfo){if(nodeInfo.templateInfo){node._templateInfo=nodeInfo.templateInfo}}function createNodeEventHandler(context,eventName,methodName){context=context._methodHost||context;let handler=function(e){if(context[methodName]){context[methodName](e,e.detail)}else{console.warn("listener method `"+methodName+"` not defined")}};return handler}const TemplateStamp=dedupingMixin((superClass=>{class TemplateStamp extends superClass{static _parseTemplate(template,outerTemplateInfo){if(!template._templateInfo){let templateInfo=template._templateInfo={};templateInfo.nodeInfoList=[];templateInfo.stripWhiteSpace=true;this._parseTemplateContent(template,templateInfo,{parent:null})}return template._templateInfo}static _parseTemplateContent(template,templateInfo,nodeInfo){return this._parseTemplateNode(template.content,templateInfo,nodeInfo)}static _parseTemplateNode(node,templateInfo,nodeInfo){let noted;let element=node;if(element.localName=="template"&&!element.hasAttribute("preserve-content")){noted=this._parseTemplateNestedTemplate(element,templateInfo,nodeInfo)||noted}else if(element.localName==="slot"){templateInfo.hasInsertionPoint=true}walker.currentNode=element;if(walker.firstChild()){noted=this._parseTemplateChildNodes(element,templateInfo,nodeInfo)||noted}if(element.hasAttributes&&element.hasAttributes()){noted=this._parseTemplateNodeAttributes(element,templateInfo,nodeInfo)||noted}return noted}static _parseTemplateChildNodes(root,templateInfo,nodeInfo){if(root.localName==="script"||root.localName==="style"){return}walker.currentNode=root;for(let node=walker.firstChild(),parentIndex=0,next;node;node=next){if(node.localName=="template"){node=wrapTemplateExtension(node)}walker.currentNode=node;next=walker.nextSibling();if(node.nodeType===Node.TEXT_NODE){let n=next;while(n&&n.nodeType===Node.TEXT_NODE){node.textContent+=n.textContent;next=walker.nextSibling();root.removeChild(n);n=next}if(templateInfo.stripWhiteSpace&&!node.textContent.trim()){root.removeChild(node);continue}}let childInfo={parentIndex:parentIndex,parentInfo:nodeInfo};if(this._parseTemplateNode(node,templateInfo,childInfo)){childInfo.infoIndex=templateInfo.nodeInfoList.push(childInfo)-1}walker.currentNode=node;if(walker.parentNode()){parentIndex++}}}static _parseTemplateNestedTemplate(node,outerTemplateInfo,nodeInfo){let templateInfo=this._parseTemplate(node,outerTemplateInfo);let content=templateInfo.content=node.content.ownerDocument.createDocumentFragment();content.appendChild(node.content);nodeInfo.templateInfo=templateInfo;return true}static _parseTemplateNodeAttributes(node,templateInfo,nodeInfo){let noted=false;let attrs=Array.from(node.attributes);for(let i=attrs.length-1,a;a=attrs[i];i--){noted=this._parseTemplateNodeAttribute(node,templateInfo,nodeInfo,a.name,a.value)||noted}return noted}static _parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value){if(name.slice(0,3)==="on-"){node.removeAttribute(name);nodeInfo.events=nodeInfo.events||[];nodeInfo.events.push({name:name.slice(3),value:value});return true}else if(name==="id"){nodeInfo.id=value;return true}return false}static _contentForTemplate(template){let templateInfo=template._templateInfo;return templateInfo&&templateInfo.content||template.content}_stampTemplate(template){if(template&&!template.content&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate){HTMLTemplateElement.decorate(template)}let templateInfo=this.constructor._parseTemplate(template);let nodeInfo=templateInfo.nodeInfoList;let content=templateInfo.content||template.content;let dom=document.importNode(content,true);dom.__noInsertionPoint=!templateInfo.hasInsertionPoint;let nodes=dom.nodeList=new Array(nodeInfo.length);dom.$={};for(let i=0,l=nodeInfo.length,info;i<l&&(info=nodeInfo[i]);i++){let node=nodes[i]=findTemplateNode(dom,info);applyIdToMap(this,dom.$,node,info);applyTemplateContent(this,node,info);applyEventListener(this,node,info)}dom=dom;return dom}_addMethodEventListenerToNode(node,eventName,methodName,context){context=context||node;let handler=createNodeEventHandler(context,eventName,methodName);this._addEventListenerToNode(node,eventName,handler);return handler}_addEventListenerToNode(node,eventName,handler){node.addEventListener(eventName,handler)}_removeEventListenerFromNode(node,eventName,handler){node.removeEventListener(eventName,handler)}}return TemplateStamp}));let dedupeId=0;const TYPES={COMPUTE:"__computeEffects",REFLECT:"__reflectEffects",NOTIFY:"__notifyEffects",PROPAGATE:"__propagateEffects",OBSERVE:"__observeEffects",READ_ONLY:"__readOnly"};const capitalAttributeRegex=/[A-Z]/;function ensureOwnEffectMap(model,type){let effects=model[type];if(!effects){effects=model[type]={}}else if(!model.hasOwnProperty(type)){effects=model[type]=Object.create(model[type]);for(let p in effects){let protoFx=effects[p];let instFx=effects[p]=Array(protoFx.length);for(let i=0;i<protoFx.length;i++){instFx[i]=protoFx[i]}}}return effects}function runEffects(inst,effects,props,oldProps,hasPaths,extraArgs){if(effects){let ran=false;let id=dedupeId++;for(let prop in props){if(runEffectsForProperty(inst,effects,id,prop,props,oldProps,hasPaths,extraArgs)){ran=true}}return ran}return false}function runEffectsForProperty(inst,effects,dedupeId,prop,props,oldProps,hasPaths,extraArgs){let ran=false;let rootProperty=hasPaths?root(prop):prop;let fxs=effects[rootProperty];if(fxs){for(let i=0,l=fxs.length,fx;i<l&&(fx=fxs[i]);i++){if((!fx.info||fx.info.lastRun!==dedupeId)&&(!hasPaths||pathMatchesTrigger(prop,fx.trigger))){if(fx.info){fx.info.lastRun=dedupeId}fx.fn(inst,prop,props,oldProps,fx.info,hasPaths,extraArgs);ran=true}}}return ran}function pathMatchesTrigger(path,trigger){if(trigger){let triggerPath=trigger.name;return triggerPath==path||!!(trigger.structured&&isAncestor(triggerPath,path))||!!(trigger.wildcard&&isDescendant(triggerPath,path))}else{return true}}function runObserverEffect(inst,property,props,oldProps,info){let fn=typeof info.method==="string"?inst[info.method]:info.method;let changedProp=info.property;if(fn){fn.call(inst,inst.__data[changedProp],oldProps[changedProp])}else if(!info.dynamicFn){console.warn("observer method `"+info.method+"` not defined")}}function runNotifyEffects(inst,notifyProps,props,oldProps,hasPaths){let fxs=inst[TYPES.NOTIFY];let notified;let id=dedupeId++;for(let prop in notifyProps){if(notifyProps[prop]){if(fxs&&runEffectsForProperty(inst,fxs,id,prop,props,oldProps,hasPaths)){notified=true}else if(hasPaths&&notifyPath(inst,prop,props)){notified=true}}}let host;if(notified&&(host=inst.__dataHost)&&host._invalidateProperties){host._invalidateProperties()}}function notifyPath(inst,path,props){let rootProperty=root(path);if(rootProperty!==path){let eventName=camelToDashCase(rootProperty)+"-changed";dispatchNotifyEvent(inst,eventName,props[path],path);return true}return false}function dispatchNotifyEvent(inst,eventName,value,path){let detail={value:value,queueProperty:true};if(path){detail.path=path}wrap(inst).dispatchEvent(new CustomEvent(eventName,{detail:detail}))}function runNotifyEffect(inst,property,props,oldProps,info,hasPaths){let rootProperty=hasPaths?root(property):property;let path=rootProperty!=property?property:null;let value=path?get(inst,path):inst.__data[property];if(path&&value===undefined){value=props[property]}dispatchNotifyEvent(inst,info.eventName,value,path)}function handleNotification(event,inst,fromProp,toPath,negate){let value;let detail=event.detail;let fromPath=detail&&detail.path;if(fromPath){toPath=translate(fromProp,toPath,fromPath);value=detail&&detail.value}else{value=event.currentTarget[fromProp]}value=negate?!value:value;if(!inst[TYPES.READ_ONLY]||!inst[TYPES.READ_ONLY][toPath]){if(inst._setPendingPropertyOrPath(toPath,value,true,Boolean(fromPath))&&(!detail||!detail.queueProperty)){inst._invalidateProperties()}}}function runReflectEffect(inst,property,props,oldProps,info){let value=inst.__data[property];if(sanitizeDOMValue){value=sanitizeDOMValue(value,info.attrName,"attribute",inst)}inst._propertyToAttribute(property,info.attrName,value)}function runComputedEffects(inst,changedProps,oldProps,hasPaths){let computeEffects=inst[TYPES.COMPUTE];if(computeEffects){let inputProps=changedProps;while(runEffects(inst,computeEffects,inputProps,oldProps,hasPaths)){Object.assign(oldProps,inst.__dataOld);Object.assign(changedProps,inst.__dataPending);inputProps=inst.__dataPending;inst.__dataPending=null}}}function runComputedEffect(inst,property,props,oldProps,info){let result=runMethodEffect(inst,property,props,oldProps,info);let computedProp=info.methodInfo;if(inst.__dataHasAccessor&&inst.__dataHasAccessor[computedProp]){inst._setPendingProperty(computedProp,result,true)}else{inst[computedProp]=result}}function computeLinkedPaths(inst,path,value){let links=inst.__dataLinkedPaths;if(links){let link;for(let a in links){let b=links[a];if(isDescendant(a,path)){link=translate(a,b,path);inst._setPendingPropertyOrPath(link,value,true,true)}else if(isDescendant(b,path)){link=translate(b,a,path);inst._setPendingPropertyOrPath(link,value,true,true)}}}}function addBinding(constructor,templateInfo,nodeInfo,kind,target,parts,literal){nodeInfo.bindings=nodeInfo.bindings||[];let binding={kind:kind,target:target,parts:parts,literal:literal,isCompound:parts.length!==1};nodeInfo.bindings.push(binding);if(shouldAddListener(binding)){let{event:event,negate:negate}=binding.parts[0];binding.listenerEvent=event||camelToDashCase(target)+"-changed";binding.listenerNegate=negate}let index=templateInfo.nodeInfoList.length;for(let i=0;i<binding.parts.length;i++){let part=binding.parts[i];part.compoundIndex=i;addEffectForBindingPart(constructor,templateInfo,binding,part,index)}}function addEffectForBindingPart(constructor,templateInfo,binding,part,index){if(!part.literal){if(binding.kind==="attribute"&&binding.target[0]==="-"){console.warn("Cannot set attribute "+binding.target+' because "-" is not a valid attribute starting character')}else{let dependencies=part.dependencies;let info={index:index,binding:binding,part:part,evaluator:constructor};for(let j=0;j<dependencies.length;j++){let trigger=dependencies[j];if(typeof trigger=="string"){trigger=parseArg(trigger);trigger.wildcard=true}constructor._addTemplatePropertyEffect(templateInfo,trigger.rootProperty,{fn:runBindingEffect,info:info,trigger:trigger})}}}}function runBindingEffect(inst,path,props,oldProps,info,hasPaths,nodeList){let node=nodeList[info.index];let binding=info.binding;let part=info.part;if(hasPaths&&part.source&&path.length>part.source.length&&binding.kind=="property"&&!binding.isCompound&&node.__isPropertyEffectsClient&&node.__dataHasAccessor&&node.__dataHasAccessor[binding.target]){let value=props[path];path=translate(part.source,binding.target,path);if(node._setPendingPropertyOrPath(path,value,false,true)){inst._enqueueClient(node)}}else{let value=info.evaluator._evaluateBinding(inst,part,path,props,oldProps,hasPaths);applyBindingValue(inst,node,binding,part,value)}}function applyBindingValue(inst,node,binding,part,value){value=computeBindingValue(node,value,binding,part);if(sanitizeDOMValue){value=sanitizeDOMValue(value,binding.target,binding.kind,node)}if(binding.kind=="attribute"){inst._valueToNodeAttribute(node,value,binding.target)}else{let prop=binding.target;if(node.__isPropertyEffectsClient&&node.__dataHasAccessor&&node.__dataHasAccessor[prop]){if(!node[TYPES.READ_ONLY]||!node[TYPES.READ_ONLY][prop]){if(node._setPendingProperty(prop,value)){inst._enqueueClient(node)}}}else{inst._setUnmanagedPropertyToNode(node,prop,value)}}}function computeBindingValue(node,value,binding,part){if(binding.isCompound){let storage=node.__dataCompoundStorage[binding.target];storage[part.compoundIndex]=value;value=storage.join("")}if(binding.kind!=="attribute"){if(binding.target==="textContent"||binding.target==="value"&&(node.localName==="input"||node.localName==="textarea")){value=value==undefined?"":value}}return value}function shouldAddListener(binding){return Boolean(binding.target)&&binding.kind!="attribute"&&binding.kind!="text"&&!binding.isCompound&&binding.parts[0].mode==="{"}function setupBindings(inst,templateInfo){let{nodeList:nodeList,nodeInfoList:nodeInfoList}=templateInfo;if(nodeInfoList.length){for(let i=0;i<nodeInfoList.length;i++){let info=nodeInfoList[i];let node=nodeList[i];let bindings=info.bindings;if(bindings){for(let i=0;i<bindings.length;i++){let binding=bindings[i];setupCompoundStorage(node,binding);addNotifyListener(node,inst,binding)}}node.__dataHost=inst}}}function setupCompoundStorage(node,binding){if(binding.isCompound){let storage=node.__dataCompoundStorage||(node.__dataCompoundStorage={});let parts=binding.parts;let literals=new Array(parts.length);for(let j=0;j<parts.length;j++){literals[j]=parts[j].literal}let target=binding.target;storage[target]=literals;if(binding.literal&&binding.kind=="property"){node[target]=binding.literal}}}function addNotifyListener(node,inst,binding){if(binding.listenerEvent){let part=binding.parts[0];node.addEventListener(binding.listenerEvent,(function(e){handleNotification(e,inst,binding.target,part.source,part.negate)}))}}function createMethodEffect(model,sig,type,effectFn,methodInfo,dynamicFn){dynamicFn=sig.static||dynamicFn&&(typeof dynamicFn!=="object"||dynamicFn[sig.methodName]);let info={methodName:sig.methodName,args:sig.args,methodInfo:methodInfo,dynamicFn:dynamicFn};for(let i=0,arg;i<sig.args.length&&(arg=sig.args[i]);i++){if(!arg.literal){model._addPropertyEffect(arg.rootProperty,type,{fn:effectFn,info:info,trigger:arg})}}if(dynamicFn){model._addPropertyEffect(sig.methodName,type,{fn:effectFn,info:info})}}function runMethodEffect(inst,property,props,oldProps,info){let context=inst._methodHost||inst;let fn=context[info.methodName];if(fn){let args=inst._marshalArgs(info.args,property,props);return fn.apply(context,args)}else if(!info.dynamicFn){console.warn("method `"+info.methodName+"` not defined")}}const emptyArray=[];const IDENT="(?:"+"[a-zA-Z_$][\\w.:$\\-*]*"+")";const NUMBER="(?:"+"[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?"+")";const SQUOTE_STRING="(?:"+"'(?:[^'\\\\]|\\\\.)*'"+")";const DQUOTE_STRING="(?:"+'"(?:[^"\\\\]|\\\\.)*"'+")";const STRING="(?:"+SQUOTE_STRING+"|"+DQUOTE_STRING+")";const ARGUMENT="(?:("+IDENT+"|"+NUMBER+"|"+STRING+")\\s*"+")";const ARGUMENTS="(?:"+ARGUMENT+"(?:,\\s*"+ARGUMENT+")*"+")";const ARGUMENT_LIST="(?:"+"\\(\\s*"+"(?:"+ARGUMENTS+"?"+")"+"\\)\\s*"+")";const BINDING="("+IDENT+"\\s*"+ARGUMENT_LIST+"?"+")";const OPEN_BRACKET="(\\[\\[|{{)"+"\\s*";const CLOSE_BRACKET="(?:]]|}})";const NEGATE="(?:(!)\\s*)?";const EXPRESSION=OPEN_BRACKET+NEGATE+BINDING+CLOSE_BRACKET;const bindingRegex=new RegExp(EXPRESSION,"g");function literalFromParts(parts){let s="";for(let i=0;i<parts.length;i++){let literal=parts[i].literal;s+=literal||""}return s}function parseMethod(expression){let m=expression.match(/([^\s]+?)\(([\s\S]*)\)/);if(m){let methodName=m[1];let sig={methodName:methodName,static:true,args:emptyArray};if(m[2].trim()){let args=m[2].replace(/\\,/g,"&comma;").split(",");return parseArgs(args,sig)}else{return sig}}return null}function parseArgs(argList,sig){sig.args=argList.map((function(rawArg){let arg=parseArg(rawArg);if(!arg.literal){sig.static=false}return arg}),this);return sig}function parseArg(rawArg){let arg=rawArg.trim().replace(/&comma;/g,",").replace(/\\(.)/g,"$1");let a={name:arg,value:"",literal:false};let fc=arg[0];if(fc==="-"){fc=arg[1]}if(fc>="0"&&fc<="9"){fc="#"}switch(fc){case"'":case'"':a.value=arg.slice(1,-1);a.literal=true;break;case"#":a.value=Number(arg);a.literal=true;break}if(!a.literal){a.rootProperty=root(arg);a.structured=isPath(arg);if(a.structured){a.wildcard=arg.slice(-2)==".*";if(a.wildcard){a.name=arg.slice(0,-2)}}}return a}function getArgValue(data,props,path){let value=get(data,path);if(value===undefined){value=props[path]}return value}function notifySplices(inst,array,path,splices){inst.notifyPath(path+".splices",{indexSplices:splices});inst.notifyPath(path+".length",array.length)}function notifySplice(inst,array,path,index,addedCount,removed){notifySplices(inst,array,path,[{index:index,addedCount:addedCount,removed:removed,object:array,type:"splice"}])}function upper(name){return name[0].toUpperCase()+name.substring(1)}const PropertyEffects=dedupingMixin((superClass=>{const propertyEffectsBase=TemplateStamp(PropertyAccessors(superClass));class PropertyEffects extends propertyEffectsBase{constructor(){super();this.__isPropertyEffectsClient=true;this.__dataCounter=0;this.__dataClientsReady;this.__dataPendingClients;this.__dataToNotify;this.__dataLinkedPaths;this.__dataHasPaths;this.__dataCompoundStorage;this.__dataHost;this.__dataTemp;this.__dataClientsInitialized;this.__data;this.__dataPending;this.__dataOld;this.__computeEffects;this.__reflectEffects;this.__notifyEffects;this.__propagateEffects;this.__observeEffects;this.__readOnly;this.__templateInfo}get PROPERTY_EFFECT_TYPES(){return TYPES}_initializeProperties(){super._initializeProperties();hostStack.registerHost(this);this.__dataClientsReady=false;this.__dataPendingClients=null;this.__dataToNotify=null;this.__dataLinkedPaths=null;this.__dataHasPaths=false;this.__dataCompoundStorage=this.__dataCompoundStorage||null;this.__dataHost=this.__dataHost||null;this.__dataTemp={};this.__dataClientsInitialized=false}_initializeProtoProperties(props){this.__data=Object.create(props);this.__dataPending=Object.create(props);this.__dataOld={}}_initializeInstanceProperties(props){let readOnly=this[TYPES.READ_ONLY];for(let prop in props){if(!readOnly||!readOnly[prop]){this.__dataPending=this.__dataPending||{};this.__dataOld=this.__dataOld||{};this.__data[prop]=this.__dataPending[prop]=props[prop]}}}_addPropertyEffect(property,type,effect){this._createPropertyAccessor(property,type==TYPES.READ_ONLY);let effects=ensureOwnEffectMap(this,type)[property];if(!effects){effects=this[type][property]=[]}effects.push(effect)}_removePropertyEffect(property,type,effect){let effects=ensureOwnEffectMap(this,type)[property];let idx=effects.indexOf(effect);if(idx>=0){effects.splice(idx,1)}}_hasPropertyEffect(property,type){let effects=this[type];return Boolean(effects&&effects[property])}_hasReadOnlyEffect(property){return this._hasPropertyEffect(property,TYPES.READ_ONLY)}_hasNotifyEffect(property){return this._hasPropertyEffect(property,TYPES.NOTIFY)}_hasReflectEffect(property){return this._hasPropertyEffect(property,TYPES.REFLECT)}_hasComputedEffect(property){return this._hasPropertyEffect(property,TYPES.COMPUTE)}_setPendingPropertyOrPath(path,value,shouldNotify,isPathNotification){if(isPathNotification||root(Array.isArray(path)?path[0]:path)!==path){if(!isPathNotification){let old=get(this,path);path=set(this,path,value);if(!path||!super._shouldPropertyChange(path,value,old)){return false}}this.__dataHasPaths=true;if(this._setPendingProperty(path,value,shouldNotify)){computeLinkedPaths(this,path,value);return true}}else{if(this.__dataHasAccessor&&this.__dataHasAccessor[path]){return this._setPendingProperty(path,value,shouldNotify)}else{this[path]=value}}return false}_setUnmanagedPropertyToNode(node,prop,value){if(value!==node[prop]||typeof value=="object"){node[prop]=value}}_setPendingProperty(property,value,shouldNotify){let propIsPath=this.__dataHasPaths&&isPath(property);let prevProps=propIsPath?this.__dataTemp:this.__data;if(this._shouldPropertyChange(property,value,prevProps[property])){if(!this.__dataPending){this.__dataPending={};this.__dataOld={}}if(!(property in this.__dataOld)){this.__dataOld[property]=this.__data[property]}if(propIsPath){this.__dataTemp[property]=value}else{this.__data[property]=value}this.__dataPending[property]=value;if(propIsPath||this[TYPES.NOTIFY]&&this[TYPES.NOTIFY][property]){this.__dataToNotify=this.__dataToNotify||{};this.__dataToNotify[property]=shouldNotify}return true}return false}_setProperty(property,value){if(this._setPendingProperty(property,value,true)){this._invalidateProperties()}}_invalidateProperties(){if(this.__dataReady){this._flushProperties()}}_enqueueClient(client){this.__dataPendingClients=this.__dataPendingClients||[];if(client!==this){this.__dataPendingClients.push(client)}}_flushProperties(){this.__dataCounter++;super._flushProperties();this.__dataCounter--}_flushClients(){if(!this.__dataClientsReady){this.__dataClientsReady=true;this._readyClients();this.__dataReady=true}else{this.__enableOrFlushClients()}}__enableOrFlushClients(){let clients=this.__dataPendingClients;if(clients){this.__dataPendingClients=null;for(let i=0;i<clients.length;i++){let client=clients[i];if(!client.__dataEnabled){client._enableProperties()}else if(client.__dataPending){client._flushProperties()}}}}_readyClients(){this.__enableOrFlushClients()}setProperties(props,setReadOnly){for(let path in props){if(setReadOnly||!this[TYPES.READ_ONLY]||!this[TYPES.READ_ONLY][path]){this._setPendingPropertyOrPath(path,props[path],true)}}this._invalidateProperties()}ready(){this._flushProperties();if(!this.__dataClientsReady){this._flushClients()}if(this.__dataPending){this._flushProperties()}}_propertiesChanged(currentProps,changedProps,oldProps){let hasPaths=this.__dataHasPaths;this.__dataHasPaths=false;runComputedEffects(this,changedProps,oldProps,hasPaths);let notifyProps=this.__dataToNotify;this.__dataToNotify=null;this._propagatePropertyChanges(changedProps,oldProps,hasPaths);this._flushClients();runEffects(this,this[TYPES.REFLECT],changedProps,oldProps,hasPaths);runEffects(this,this[TYPES.OBSERVE],changedProps,oldProps,hasPaths);if(notifyProps){runNotifyEffects(this,notifyProps,changedProps,oldProps,hasPaths)}if(this.__dataCounter==1){this.__dataTemp={}}}_propagatePropertyChanges(changedProps,oldProps,hasPaths){if(this[TYPES.PROPAGATE]){runEffects(this,this[TYPES.PROPAGATE],changedProps,oldProps,hasPaths)}let templateInfo=this.__templateInfo;while(templateInfo){runEffects(this,templateInfo.propertyEffects,changedProps,oldProps,hasPaths,templateInfo.nodeList);templateInfo=templateInfo.nextTemplateInfo}}linkPaths(to,from){to=normalize(to);from=normalize(from);this.__dataLinkedPaths=this.__dataLinkedPaths||{};this.__dataLinkedPaths[to]=from}unlinkPaths(path){path=normalize(path);if(this.__dataLinkedPaths){delete this.__dataLinkedPaths[path]}}notifySplices(path,splices){let info={path:""};let array=get(this,path,info);notifySplices(this,array,info.path,splices)}get(path,root){return get(root||this,path)}set(path,value,root){if(root){set(root,path,value)}else{if(!this[TYPES.READ_ONLY]||!this[TYPES.READ_ONLY][path]){if(this._setPendingPropertyOrPath(path,value,true)){this._invalidateProperties()}}}}push(path,...items){let info={path:""};let array=get(this,path,info);let len=array.length;let ret=array.push(...items);if(items.length){notifySplice(this,array,info.path,len,items.length,[])}return ret}pop(path){let info={path:""};let array=get(this,path,info);let hadLength=Boolean(array.length);let ret=array.pop();if(hadLength){notifySplice(this,array,info.path,array.length,0,[ret])}return ret}splice(path,start,deleteCount,...items){let info={path:""};let array=get(this,path,info);if(start<0){start=array.length-Math.floor(-start)}else if(start){start=Math.floor(start)}let ret;if(arguments.length===2){ret=array.splice(start)}else{ret=array.splice(start,deleteCount,...items)}if(items.length||ret.length){notifySplice(this,array,info.path,start,items.length,ret)}return ret}shift(path){let info={path:""};let array=get(this,path,info);let hadLength=Boolean(array.length);let ret=array.shift();if(hadLength){notifySplice(this,array,info.path,0,0,[ret])}return ret}unshift(path,...items){let info={path:""};let array=get(this,path,info);let ret=array.unshift(...items);if(items.length){notifySplice(this,array,info.path,0,items.length,[])}return ret}notifyPath(path,value){let propPath;if(arguments.length==1){let info={path:""};value=get(this,path,info);propPath=info.path}else if(Array.isArray(path)){propPath=normalize(path)}else{propPath=path}if(this._setPendingPropertyOrPath(propPath,value,true,true)){this._invalidateProperties()}}_createReadOnlyProperty(property,protectedSetter){this._addPropertyEffect(property,TYPES.READ_ONLY);if(protectedSetter){this["_set"+upper(property)]=function(value){this._setProperty(property,value)}}}_createPropertyObserver(property,method,dynamicFn){let info={property:property,method:method,dynamicFn:Boolean(dynamicFn)};this._addPropertyEffect(property,TYPES.OBSERVE,{fn:runObserverEffect,info:info,trigger:{name:property}});if(dynamicFn){this._addPropertyEffect(method,TYPES.OBSERVE,{fn:runObserverEffect,info:info,trigger:{name:method}})}}_createMethodObserver(expression,dynamicFn){let sig=parseMethod(expression);if(!sig){throw new Error("Malformed observer expression '"+expression+"'")}createMethodEffect(this,sig,TYPES.OBSERVE,runMethodEffect,null,dynamicFn)}_createNotifyingProperty(property){this._addPropertyEffect(property,TYPES.NOTIFY,{fn:runNotifyEffect,info:{eventName:camelToDashCase(property)+"-changed",property:property}})}_createReflectedProperty(property){let attr=this.constructor.attributeNameForProperty(property);if(attr[0]==="-"){console.warn("Property "+property+" cannot be reflected to attribute "+attr+' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.')}else{this._addPropertyEffect(property,TYPES.REFLECT,{fn:runReflectEffect,info:{attrName:attr}})}}_createComputedProperty(property,expression,dynamicFn){let sig=parseMethod(expression);if(!sig){throw new Error("Malformed computed expression '"+expression+"'")}createMethodEffect(this,sig,TYPES.COMPUTE,runComputedEffect,property,dynamicFn)}_marshalArgs(args,path,props){const data=this.__data;const values=[];for(let i=0,l=args.length;i<l;i++){let{name:name,structured:structured,wildcard:wildcard,value:value,literal:literal}=args[i];if(!literal){if(wildcard){const matches=isDescendant(name,path);const pathValue=getArgValue(data,props,matches?path:name);value={path:matches?path:name,value:pathValue,base:matches?get(data,name):pathValue}}else{value=structured?getArgValue(data,props,name):data[name]}}values[i]=value}return values}static addPropertyEffect(property,type,effect){this.prototype._addPropertyEffect(property,type,effect)}static createPropertyObserver(property,method,dynamicFn){this.prototype._createPropertyObserver(property,method,dynamicFn)}static createMethodObserver(expression,dynamicFn){this.prototype._createMethodObserver(expression,dynamicFn)}static createNotifyingProperty(property){this.prototype._createNotifyingProperty(property)}static createReadOnlyProperty(property,protectedSetter){this.prototype._createReadOnlyProperty(property,protectedSetter)}static createReflectedProperty(property){this.prototype._createReflectedProperty(property)}static createComputedProperty(property,expression,dynamicFn){this.prototype._createComputedProperty(property,expression,dynamicFn)}static bindTemplate(template){return this.prototype._bindTemplate(template)}_bindTemplate(template,instanceBinding){let templateInfo=this.constructor._parseTemplate(template);let wasPreBound=this.__templateInfo==templateInfo;if(!wasPreBound){for(let prop in templateInfo.propertyEffects){this._createPropertyAccessor(prop)}}if(instanceBinding){templateInfo=Object.create(templateInfo);templateInfo.wasPreBound=wasPreBound;if(!wasPreBound&&this.__templateInfo){let last=this.__templateInfoLast||this.__templateInfo;this.__templateInfoLast=last.nextTemplateInfo=templateInfo;templateInfo.previousTemplateInfo=last;return templateInfo}}return this.__templateInfo=templateInfo}static _addTemplatePropertyEffect(templateInfo,prop,effect){let hostProps=templateInfo.hostProps=templateInfo.hostProps||{};hostProps[prop]=true;let effects=templateInfo.propertyEffects=templateInfo.propertyEffects||{};let propEffects=effects[prop]=effects[prop]||[];propEffects.push(effect)}_stampTemplate(template){hostStack.beginHosting(this);let dom=super._stampTemplate(template);hostStack.endHosting(this);let templateInfo=this._bindTemplate(template,true);templateInfo.nodeList=dom.nodeList;if(!templateInfo.wasPreBound){let nodes=templateInfo.childNodes=[];for(let n=dom.firstChild;n;n=n.nextSibling){nodes.push(n)}}dom.templateInfo=templateInfo;setupBindings(this,templateInfo);if(this.__dataReady){runEffects(this,templateInfo.propertyEffects,this.__data,null,false,templateInfo.nodeList)}return dom}_removeBoundDom(dom){let templateInfo=dom.templateInfo;if(templateInfo.previousTemplateInfo){templateInfo.previousTemplateInfo.nextTemplateInfo=templateInfo.nextTemplateInfo}if(templateInfo.nextTemplateInfo){templateInfo.nextTemplateInfo.previousTemplateInfo=templateInfo.previousTemplateInfo}if(this.__templateInfoLast==templateInfo){this.__templateInfoLast=templateInfo.previousTemplateInfo}templateInfo.previousTemplateInfo=templateInfo.nextTemplateInfo=null;let nodes=templateInfo.childNodes;for(let i=0;i<nodes.length;i++){let node=nodes[i];node.parentNode.removeChild(node)}}static _parseTemplateNode(node,templateInfo,nodeInfo){let noted=super._parseTemplateNode(node,templateInfo,nodeInfo);if(node.nodeType===Node.TEXT_NODE){let parts=this._parseBindings(node.textContent,templateInfo);if(parts){node.textContent=literalFromParts(parts)||" ";addBinding(this,templateInfo,nodeInfo,"text","textContent",parts);noted=true}}return noted}static _parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value){let parts=this._parseBindings(value,templateInfo);if(parts){let origName=name;let kind="property";if(capitalAttributeRegex.test(name)){kind="attribute"}else if(name[name.length-1]=="$"){name=name.slice(0,-1);kind="attribute"}let literal=literalFromParts(parts);if(literal&&kind=="attribute"){if(name=="class"&&node.hasAttribute("class")){literal+=" "+node.getAttribute(name)}node.setAttribute(name,literal)}if(node.localName==="input"&&origName==="value"){node.setAttribute(origName,"")}node.removeAttribute(origName);if(kind==="property"){name=dashToCamelCase(name)}addBinding(this,templateInfo,nodeInfo,kind,name,parts,literal);return true}else{return super._parseTemplateNodeAttribute(node,templateInfo,nodeInfo,name,value)}}static _parseTemplateNestedTemplate(node,templateInfo,nodeInfo){let noted=super._parseTemplateNestedTemplate(node,templateInfo,nodeInfo);let hostProps=nodeInfo.templateInfo.hostProps;let mode="{";for(let source in hostProps){let parts=[{mode:mode,source:source,dependencies:[source]}];addBinding(this,templateInfo,nodeInfo,"property","_host_"+source,parts)}return noted}static _parseBindings(text,templateInfo){let parts=[];let lastIndex=0;let m;while((m=bindingRegex.exec(text))!==null){if(m.index>lastIndex){parts.push({literal:text.slice(lastIndex,m.index)})}let mode=m[1][0];let negate=Boolean(m[2]);let source=m[3].trim();let customEvent=false,notifyEvent="",colon=-1;if(mode=="{"&&(colon=source.indexOf("::"))>0){notifyEvent=source.substring(colon+2);source=source.substring(0,colon);customEvent=true}let signature=parseMethod(source);let dependencies=[];if(signature){let{args:args,methodName:methodName}=signature;for(let i=0;i<args.length;i++){let arg=args[i];if(!arg.literal){dependencies.push(arg)}}let dynamicFns=templateInfo.dynamicFns;if(dynamicFns&&dynamicFns[methodName]||signature.static){dependencies.push(methodName);signature.dynamicFn=true}}else{dependencies.push(source)}parts.push({source:source,mode:mode,negate:negate,customEvent:customEvent,signature:signature,dependencies:dependencies,event:notifyEvent});lastIndex=bindingRegex.lastIndex}if(lastIndex&&lastIndex<text.length){let literal=text.substring(lastIndex);if(literal){parts.push({literal:literal})}}if(parts.length){return parts}else{return null}}static _evaluateBinding(inst,part,path,props,oldProps,hasPaths){let value;if(part.signature){value=runMethodEffect(inst,path,props,oldProps,part.signature)}else if(path!=part.source){value=get(inst,part.source)}else{if(hasPaths&&isPath(path)){value=get(inst,path)}else{value=inst.__data[path]}}if(part.negate){value=!value}return value}}return PropertyEffects}));class HostStack{constructor(){this.stack=[]}registerHost(inst){if(this.stack.length){let host=this.stack[this.stack.length-1];host._enqueueClient(inst)}}beginHosting(inst){this.stack.push(inst)}endHosting(inst){let stackLen=this.stack.length;if(stackLen&&this.stack[stackLen-1]==inst){this.stack.pop()}}}const hostStack=new HostStack;function register(prototype){}function normalizeProperties(props){const output={};for(let p in props){const o=props[p];output[p]=typeof o==="function"?{type:o}:o}return output}const PropertiesMixin=dedupingMixin((superClass=>{const base=PropertiesChanged(superClass);function superPropertiesClass(constructor){const superCtor=Object.getPrototypeOf(constructor);return superCtor.prototype instanceof PropertiesMixin?superCtor:null}function ownProperties(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__ownProperties",constructor))){let props=null;if(constructor.hasOwnProperty(JSCompiler_renameProperty("properties",constructor))){const properties=constructor.properties;if(properties){props=normalizeProperties(properties)}}constructor.__ownProperties=props}return constructor.__ownProperties}class PropertiesMixin extends base{static get observedAttributes(){if(!this.hasOwnProperty("__observedAttributes")){register(this.prototype);const props=this._properties;this.__observedAttributes=props?Object.keys(props).map((p=>this.attributeNameForProperty(p))):[]}return this.__observedAttributes}static finalize(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__finalized",this))){const superCtor=superPropertiesClass(this);if(superCtor){superCtor.finalize()}this.__finalized=true;this._finalizeClass()}}static _finalizeClass(){const props=ownProperties(this);if(props){this.createProperties(props)}}static get _properties(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__properties",this))){const superCtor=superPropertiesClass(this);this.__properties=Object.assign({},superCtor&&superCtor._properties,ownProperties(this))}return this.__properties}static typeForProperty(name){const info=this._properties[name];return info&&info.type}_initializeProperties(){this.constructor.finalize();super._initializeProperties()}connectedCallback(){if(super.connectedCallback){super.connectedCallback()}this._enableProperties()}disconnectedCallback(){if(super.disconnectedCallback){super.disconnectedCallback()}}}return PropertiesMixin}));const version="3.2.0";const builtCSS=window.ShadyCSS&&window.ShadyCSS["cssBuild"];const ElementMixin=dedupingMixin((base=>{const polymerElementBase=PropertiesMixin(PropertyEffects(base));function propertyDefaults(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__propertyDefaults",constructor))){constructor.__propertyDefaults=null;let props=constructor._properties;for(let p in props){let info=props[p];if("value"in info){constructor.__propertyDefaults=constructor.__propertyDefaults||{};constructor.__propertyDefaults[p]=info}}}return constructor.__propertyDefaults}function ownObservers(constructor){if(!constructor.hasOwnProperty(JSCompiler_renameProperty("__ownObservers",constructor))){constructor.__ownObservers=constructor.hasOwnProperty(JSCompiler_renameProperty("observers",constructor))?constructor.observers:null}return constructor.__ownObservers}function createPropertyFromConfig(proto,name,info,allProps){if(info.computed){info.readOnly=true}if(info.computed){if(proto._hasReadOnlyEffect(name)){console.warn(`Cannot redefine computed property '${name}'.`)}else{proto._createComputedProperty(name,info.computed,allProps)}}if(info.readOnly&&!proto._hasReadOnlyEffect(name)){proto._createReadOnlyProperty(name,!info.computed)}else if(info.readOnly===false&&proto._hasReadOnlyEffect(name)){console.warn(`Cannot make readOnly property '${name}' non-readOnly.`)}if(info.reflectToAttribute&&!proto._hasReflectEffect(name)){proto._createReflectedProperty(name)}else if(info.reflectToAttribute===false&&proto._hasReflectEffect(name)){console.warn(`Cannot make reflected property '${name}' non-reflected.`)}if(info.notify&&!proto._hasNotifyEffect(name)){proto._createNotifyingProperty(name)}else if(info.notify===false&&proto._hasNotifyEffect(name)){console.warn(`Cannot make notify property '${name}' non-notify.`)}if(info.observer){proto._createPropertyObserver(name,info.observer,allProps[info.observer])}proto._addPropertyToAttributeMap(name)}function processElementStyles(klass,template,is,baseURI){if(!builtCSS){const templateStyles=template.content.querySelectorAll("style");const stylesWithImports=stylesFromTemplate(template);const linkedStyles=stylesFromModuleImports(is);const firstTemplateChild=template.content.firstElementChild;for(let idx=0;idx<linkedStyles.length;idx++){let s=linkedStyles[idx];s.textContent=klass._processStyleText(s.textContent,baseURI);template.content.insertBefore(s,firstTemplateChild)}let templateStyleIndex=0;for(let i=0;i<stylesWithImports.length;i++){let s=stylesWithImports[i];let templateStyle=templateStyles[templateStyleIndex];if(templateStyle!==s){s=s.cloneNode(true);templateStyle.parentNode.insertBefore(s,templateStyle)}else{templateStyleIndex++}s.textContent=klass._processStyleText(s.textContent,baseURI)}}if(window.ShadyCSS){window.ShadyCSS.prepareTemplate(template,is)}}function getTemplateFromDomModule(is){let template=null;if(is&&!strictTemplatePolicy){template=DomModule.import(is,"template")}return template}class PolymerElement extends polymerElementBase{static get polymerElementVersion(){return version}static _finalizeClass(){super._finalizeClass();const observers=ownObservers(this);if(observers){this.createObservers(observers,this._properties)}this._prepareTemplate()}static _prepareTemplate(){let template=this.template;if(template){if(typeof template==="string"){console.error("template getter must return HTMLTemplateElement");template=null}else{template=template.cloneNode(true)}}this.prototype._template=template}static createProperties(props){for(let p in props){createPropertyFromConfig(this.prototype,p,props[p],props)}}static createObservers(observers,dynamicFns){const proto=this.prototype;for(let i=0;i<observers.length;i++){proto._createMethodObserver(observers[i],dynamicFns)}}static get template(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_template",this))){this._template=this.prototype.hasOwnProperty(JSCompiler_renameProperty("_template",this.prototype))?this.prototype._template:getTemplateFromDomModule(this.is)||Object.getPrototypeOf(this.prototype).constructor.template}return this._template}static set template(value){this._template=value}static get importPath(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_importPath",this))){const meta=this.importMeta;if(meta){this._importPath=pathFromUrl(meta.url)}else{const module=DomModule.import(this.is);this._importPath=module&&module.assetpath||Object.getPrototypeOf(this.prototype).constructor.importPath}}return this._importPath}constructor(){super();this._template;this._importPath;this.rootPath;this.importPath;this.root;this.$}_initializeProperties(){this.constructor.finalize();this.constructor._finalizeTemplate(this.localName);super._initializeProperties();this.rootPath=rootPath;this.importPath=this.constructor.importPath;let p$=propertyDefaults(this.constructor);if(!p$){return}for(let p in p$){let info=p$[p];if(!this.hasOwnProperty(p)){let value=typeof info.value=="function"?info.value.call(this):info.value;if(this._hasAccessor(p)){this._setPendingProperty(p,value,true)}else{this[p]=value}}}}static _processStyleText(cssText,baseURI){return resolveCss(cssText,baseURI)}static _finalizeTemplate(is){const template=this.prototype._template;if(template&&!template.__polymerFinalized){template.__polymerFinalized=true;const importPath=this.importPath;const baseURI=importPath?resolveUrl(importPath):"";processElementStyles(this,template,is,baseURI);this.prototype._bindTemplate(template)}}connectedCallback(){if(window.ShadyCSS&&this._template){window.ShadyCSS.styleElement(this)}super.connectedCallback()}ready(){if(this._template){this.root=this._stampTemplate(this._template);this.$=this.root.$}super.ready()}_readyClients(){if(this._template){this.root=this._attachDom(this.root)}super._readyClients()}_attachDom(dom){const n=wrap(this);if(n.attachShadow){if(dom){if(!n.shadowRoot){n.attachShadow({mode:"open"})}n.shadowRoot.appendChild(dom);return n.shadowRoot}return null}else{throw new Error("ShadowDOM not available. "+"PolymerElement can create dom as children instead of in "+"ShadowDOM by setting `this.root = this;` before `ready`.")}}updateStyles(properties){if(window.ShadyCSS){window.ShadyCSS.styleSubtree(this,properties)}}resolveUrl(url,base){if(!base&&this.importPath){base=resolveUrl(this.importPath)}return resolveUrl(url,base)}static _parseTemplateContent(template,templateInfo,nodeInfo){templateInfo.dynamicFns=templateInfo.dynamicFns||this._properties;return super._parseTemplateContent(template,templateInfo,nodeInfo)}static _addTemplatePropertyEffect(templateInfo,prop,effect){return super._addTemplatePropertyEffect(templateInfo,prop,effect)}}return PolymerElement}));class LiteralString{constructor(string){this.value=string.toString()}toString(){return this.value}}function literalValue(value){if(value instanceof LiteralString){return value.value}else{throw new Error(`non-literal value passed to Polymer's htmlLiteral function: ${value}`)}}function htmlValue(value){if(value instanceof HTMLTemplateElement){return value.innerHTML}else if(value instanceof LiteralString){return literalValue(value)}else{throw new Error(`non-template value passed to Polymer's html function: ${value}`)}}const html=function html(strings,...values){const template=document.createElement("template");template.innerHTML=values.reduce(((acc,v,idx)=>acc+htmlValue(v)+strings[idx+1]),strings[0]);return template};const PolymerElement=ElementMixin(HTMLElement);function mutablePropertyChange$1(inst,property,value,old,mutableData){let isObject;if(mutableData){isObject=typeof value==="object"&&value!==null;if(isObject){old=inst.__dataTemp[property]}}let shouldChange=old!==value&&(old===old||value===value);if(isObject&&shouldChange){inst.__dataTemp[property]=value}return shouldChange}const MutableData=dedupingMixin((superClass=>{class MutableData extends superClass{_shouldPropertyChange(property,value,old){return mutablePropertyChange$1(this,property,value,old,true)}}return MutableData}));const OptionalMutableData=dedupingMixin((superClass=>{class OptionalMutableData extends superClass{static get properties(){return{mutableData:Boolean}}_shouldPropertyChange(property,value,old){return mutablePropertyChange$1(this,property,value,old,this.mutableData)}}return OptionalMutableData}));MutableData._mutablePropertyChange=mutablePropertyChange$1;let newInstance=null;function HTMLTemplateElementExtension(){return newInstance}HTMLTemplateElementExtension.prototype=Object.create(HTMLTemplateElement.prototype,{constructor:{value:HTMLTemplateElementExtension,writable:true}});const DataTemplate=PropertyEffects(HTMLTemplateElementExtension);const MutableDataTemplate=MutableData(DataTemplate);function upgradeTemplate(template,constructor){newInstance=template;Object.setPrototypeOf(template,constructor.prototype);new constructor;newInstance=null}const templateInstanceBase=PropertyEffects(class{});class TemplateInstanceBase extends templateInstanceBase{constructor(props){super();this._configureProperties(props);this.root=this._stampTemplate(this.__dataHost);let children=this.children=[];for(let n=this.root.firstChild;n;n=n.nextSibling){children.push(n);n.__templatizeInstance=this}if(this.__templatizeOwner&&this.__templatizeOwner.__hideTemplateChildren__){this._showHideChildren(true)}let options=this.__templatizeOptions;if(props&&options.instanceProps||!options.instanceProps){this._enableProperties()}}_configureProperties(props){let options=this.__templatizeOptions;if(options.forwardHostProp){for(let hprop in this.__hostProps){this._setPendingProperty(hprop,this.__dataHost["_host_"+hprop])}}for(let iprop in props){this._setPendingProperty(iprop,props[iprop])}}forwardHostProp(prop,value){if(this._setPendingPropertyOrPath(prop,value,false,true)){this.__dataHost._enqueueClient(this)}}_addEventListenerToNode(node,eventName,handler){if(this._methodHost&&this.__templatizeOptions.parentModel){this._methodHost._addEventListenerToNode(node,eventName,(e=>{e.model=this;handler(e)}))}else{let templateHost=this.__dataHost.__dataHost;if(templateHost){templateHost._addEventListenerToNode(node,eventName,handler)}}}_showHideChildren(hide){let c=this.children;for(let i=0;i<c.length;i++){let n=c[i];if(Boolean(hide)!=Boolean(n.__hideTemplateChildren__)){if(n.nodeType===Node.TEXT_NODE){if(hide){n.__polymerTextContent__=n.textContent;n.textContent=""}else{n.textContent=n.__polymerTextContent__}}else if(n.localName==="slot"){if(hide){n.__polymerReplaced__=document.createComment("hidden-slot");wrap(wrap(n).parentNode).replaceChild(n.__polymerReplaced__,n)}else{const replace=n.__polymerReplaced__;if(replace){wrap(wrap(replace).parentNode).replaceChild(n,replace)}}}else if(n.style){if(hide){n.__polymerDisplay__=n.style.display;n.style.display="none"}else{n.style.display=n.__polymerDisplay__}}}n.__hideTemplateChildren__=hide;if(n._showHideChildren){n._showHideChildren(hide)}}}_setUnmanagedPropertyToNode(node,prop,value){if(node.__hideTemplateChildren__&&node.nodeType==Node.TEXT_NODE&&prop=="textContent"){node.__polymerTextContent__=value}else{super._setUnmanagedPropertyToNode(node,prop,value)}}get parentModel(){let model=this.__parentModel;if(!model){let options;model=this;do{model=model.__dataHost.__dataHost}while((options=model.__templatizeOptions)&&!options.parentModel);this.__parentModel=model}return model}dispatchEvent(event){return true}}TemplateInstanceBase.prototype.__dataHost;TemplateInstanceBase.prototype.__templatizeOptions;TemplateInstanceBase.prototype._methodHost;TemplateInstanceBase.prototype.__templatizeOwner;TemplateInstanceBase.prototype.__hostProps;const MutableTemplateInstanceBase=MutableData(TemplateInstanceBase);function findMethodHost(template){let templateHost=template.__dataHost;return templateHost&&templateHost._methodHost||templateHost}function createTemplatizerClass(template,templateInfo,options){let templatizerBase=options.mutableData?MutableTemplateInstanceBase:TemplateInstanceBase;if(templatize.mixin){templatizerBase=templatize.mixin(templatizerBase)}let klass=class extends templatizerBase{};klass.prototype.__templatizeOptions=options;klass.prototype._bindTemplate(template);addNotifyEffects(klass,template,templateInfo,options);return klass}function addPropagateEffects(template,templateInfo,options){let userForwardHostProp=options.forwardHostProp;if(userForwardHostProp){let klass=templateInfo.templatizeTemplateClass;if(!klass){let templatizedBase=options.mutableData?MutableDataTemplate:DataTemplate;klass=templateInfo.templatizeTemplateClass=class TemplatizedTemplate extends templatizedBase{};let hostProps=templateInfo.hostProps;for(let prop in hostProps){klass.prototype._addPropertyEffect("_host_"+prop,klass.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE,{fn:createForwardHostPropEffect(prop,userForwardHostProp)});klass.prototype._createNotifyingProperty("_host_"+prop)}}upgradeTemplate(template,klass);if(template.__dataProto){Object.assign(template.__data,template.__dataProto)}template.__dataTemp={};template.__dataPending=null;template.__dataOld=null;template._enableProperties()}}function createForwardHostPropEffect(hostProp,userForwardHostProp){return function forwardHostProp(template,prop,props){userForwardHostProp.call(template.__templatizeOwner,prop.substring("_host_".length),props[prop])}}function addNotifyEffects(klass,template,templateInfo,options){let hostProps=templateInfo.hostProps||{};for(let iprop in options.instanceProps){delete hostProps[iprop];let userNotifyInstanceProp=options.notifyInstanceProp;if(userNotifyInstanceProp){klass.prototype._addPropertyEffect(iprop,klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:createNotifyInstancePropEffect(iprop,userNotifyInstanceProp)})}}if(options.forwardHostProp&&template.__dataHost){for(let hprop in hostProps){klass.prototype._addPropertyEffect(hprop,klass.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:createNotifyHostPropEffect()})}}}function createNotifyInstancePropEffect(instProp,userNotifyInstanceProp){return function notifyInstanceProp(inst,prop,props){userNotifyInstanceProp.call(inst.__templatizeOwner,inst,prop,props[prop])}}function createNotifyHostPropEffect(){return function notifyHostProp(inst,prop,props){inst.__dataHost._setPendingPropertyOrPath("_host_"+prop,props[prop],true,true)}}function templatize(template,owner,options){options=options||{};if(template.__templatizeOwner){throw new Error("A <template> can only be templatized once")}template.__templatizeOwner=owner;const ctor=owner?owner.constructor:TemplateInstanceBase;let templateInfo=ctor._parseTemplate(template);let baseClass=templateInfo.templatizeInstanceClass;if(!baseClass){baseClass=createTemplatizerClass(template,templateInfo,options);templateInfo.templatizeInstanceClass=baseClass}addPropagateEffects(template,templateInfo,options);let klass=class TemplateInstance extends baseClass{};klass.prototype._methodHost=findMethodHost(template);klass.prototype.__dataHost=template;klass.prototype.__templatizeOwner=owner;klass.prototype.__hostProps=templateInfo.hostProps;klass=klass;return klass}function modelForElement(template,node){let model;while(node){if(model=node.__templatizeInstance){if(model.__dataHost!=template){node=model.__dataHost}else{return model}}else{node=wrap(node).parentNode}}return null}const flush=function(){let shadyDOM,debouncers;do{shadyDOM=window.ShadyDOM&&ShadyDOM.flush();if(window.ShadyCSS&&window.ShadyCSS.ScopingShim){window.ShadyCSS.ScopingShim.flush()}debouncers=flushDebouncers()}while(shadyDOM||debouncers)};class DomIf extends PolymerElement{static get is(){return"dom-if"}static get template(){return null}static get properties(){return{if:{type:Boolean,observer:"__debounceRender"},restamp:{type:Boolean,observer:"__debounceRender"}}}constructor(){super();this.__renderDebouncer=null;this.__invalidProps=null;this.__instance=null;this._lastIf=false;this.__ctor=null;this.__hideTemplateChildren__=false}__debounceRender(){this.__renderDebouncer=Debouncer.debounce(this.__renderDebouncer,microTask,(()=>this.__render()));enqueueDebouncer(this.__renderDebouncer)}disconnectedCallback(){super.disconnectedCallback();const parent=wrap(this).parentNode;if(!parent||parent.nodeType==Node.DOCUMENT_FRAGMENT_NODE&&!wrap(parent).host){this.__teardownInstance()}}connectedCallback(){super.connectedCallback();this.style.display="none";if(this.if){this.__debounceRender()}}render(){flush()}__render(){if(this.if){if(!this.__ensureInstance()){return}this._showHideChildren()}else if(this.restamp){this.__teardownInstance()}if(!this.restamp&&this.__instance){this._showHideChildren()}if(this.if!=this._lastIf){this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}));this._lastIf=this.if}}__ensureInstance(){let parentNode=wrap(this).parentNode;if(parentNode){if(!this.__ctor){let template=wrap(this).querySelector("template");if(!template){let observer=new MutationObserver((()=>{if(wrap(this).querySelector("template")){observer.disconnect();this.__render()}else{throw new Error("dom-if requires a <template> child")}}));observer.observe(this,{childList:true});return false}this.__ctor=templatize(template,this,{mutableData:true,forwardHostProp:function(prop,value){if(this.__instance){if(this.if){this.__instance.forwardHostProp(prop,value)}else{this.__invalidProps=this.__invalidProps||Object.create(null);this.__invalidProps[root(prop)]=true}}}})}if(!this.__instance){this.__instance=new this.__ctor;wrap(parentNode).insertBefore(this.__instance.root,this)}else{this.__syncHostProperties();let c$=this.__instance.children;if(c$&&c$.length){let lastChild=wrap(this).previousSibling;if(lastChild!==c$[c$.length-1]){for(let i=0,n;i<c$.length&&(n=c$[i]);i++){wrap(parentNode).insertBefore(n,this)}}}}}return true}__syncHostProperties(){let props=this.__invalidProps;if(props){for(let prop in props){this.__instance._setPendingProperty(prop,this.__dataHost[prop])}this.__invalidProps=null;this.__instance._flushProperties()}}__teardownInstance(){if(this.__instance){let c$=this.__instance.children;if(c$&&c$.length){let parent=wrap(c$[0]).parentNode;if(parent){parent=wrap(parent);for(let i=0,n;i<c$.length&&(n=c$[i]);i++){parent.removeChild(n)}}}this.__instance=null;this.__invalidProps=null}}_showHideChildren(){let hidden=this.__hideTemplateChildren__||!this.if;if(this.__instance){this.__instance._showHideChildren(hidden)}}}customElements.define(DomIf.is,DomIf);const domRepeatBase=OptionalMutableData(PolymerElement);class DomRepeat extends domRepeatBase{static get is(){return"dom-repeat"}static get template(){return null}static get properties(){return{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},itemsIndexAs:{type:String,value:"itemsIndex"},sort:{type:Function,observer:"__sortChanged"},filter:{type:Function,observer:"__filterChanged"},observe:{type:String,observer:"__observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:true,readOnly:true},initialCount:{type:Number,observer:"__initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"__computeFrameTime(targetFramerate)"}}}static get observers(){return["__itemsChanged(items.*)"]}constructor(){super();this.__instances=[];this.__limit=Infinity;this.__pool=[];this.__renderDebouncer=null;this.__itemsIdxToInstIdx={};this.__chunkCount=null;this.__lastChunkTime=null;this.__sortFn=null;this.__filterFn=null;this.__observePaths=null;this.__ctor=null;this.__isDetached=true;this.template=null}disconnectedCallback(){super.disconnectedCallback();this.__isDetached=true;for(let i=0;i<this.__instances.length;i++){this.__detachInstance(i)}}connectedCallback(){super.connectedCallback();this.style.display="none";if(this.__isDetached){this.__isDetached=false;let wrappedParent=wrap(wrap(this).parentNode);for(let i=0;i<this.__instances.length;i++){this.__attachInstance(i,wrappedParent)}}}__ensureTemplatized(){if(!this.__ctor){let template=this.template=this.querySelector("template");if(!template){let observer=new MutationObserver((()=>{if(this.querySelector("template")){observer.disconnect();this.__render()}else{throw new Error("dom-repeat requires a <template> child")}}));observer.observe(this,{childList:true});return false}let instanceProps={};instanceProps[this.as]=true;instanceProps[this.indexAs]=true;instanceProps[this.itemsIndexAs]=true;this.__ctor=templatize(template,this,{mutableData:this.mutableData,parentModel:true,instanceProps:instanceProps,forwardHostProp:function(prop,value){let i$=this.__instances;for(let i=0,inst;i<i$.length&&(inst=i$[i]);i++){inst.forwardHostProp(prop,value)}},notifyInstanceProp:function(inst,prop,value){if(matches(this.as,prop)){let idx=inst[this.itemsIndexAs];if(prop==this.as){this.items[idx]=value}let path=translate(this.as,`${JSCompiler_renameProperty("items",this)}.${idx}`,prop);this.notifyPath(path,value)}}})}return true}__getMethodHost(){return this.__dataHost._methodHost||this.__dataHost}__functionFromPropertyValue(functionOrMethodName){if(typeof functionOrMethodName==="string"){let methodName=functionOrMethodName;let obj=this.__getMethodHost();return function(){return obj[methodName].apply(obj,arguments)}}return functionOrMethodName}__sortChanged(sort){this.__sortFn=this.__functionFromPropertyValue(sort);if(this.items){this.__debounceRender(this.__render)}}__filterChanged(filter){this.__filterFn=this.__functionFromPropertyValue(filter);if(this.items){this.__debounceRender(this.__render)}}__computeFrameTime(rate){return Math.ceil(1e3/rate)}__initializeChunking(){if(this.initialCount){this.__limit=this.initialCount;this.__chunkCount=this.initialCount;this.__lastChunkTime=performance.now()}}__tryRenderChunk(){if(this.items&&this.__limit<this.items.length){this.__debounceRender(this.__requestRenderChunk)}}__requestRenderChunk(){requestAnimationFrame((()=>this.__renderChunk()))}__renderChunk(){let currChunkTime=performance.now();let ratio=this._targetFrameTime/(currChunkTime-this.__lastChunkTime);this.__chunkCount=Math.round(this.__chunkCount*ratio)||1;this.__limit+=this.__chunkCount;this.__lastChunkTime=currChunkTime;this.__debounceRender(this.__render)}__observeChanged(){this.__observePaths=this.observe&&this.observe.replace(".*",".").split(" ")}__itemsChanged(change){if(this.items&&!Array.isArray(this.items)){console.warn("dom-repeat expected array for `items`, found",this.items)}if(!this.__handleItemPath(change.path,change.value)){this.__initializeChunking();this.__debounceRender(this.__render)}}__handleObservedPaths(path){if(this.__sortFn||this.__filterFn){if(!path){this.__debounceRender(this.__render,this.delay)}else if(this.__observePaths){let paths=this.__observePaths;for(let i=0;i<paths.length;i++){if(path.indexOf(paths[i])===0){this.__debounceRender(this.__render,this.delay)}}}}}__debounceRender(fn,delay=0){this.__renderDebouncer=Debouncer.debounce(this.__renderDebouncer,delay>0?timeOut.after(delay):microTask,fn.bind(this));enqueueDebouncer(this.__renderDebouncer)}render(){this.__debounceRender(this.__render);flush()}__render(){if(!this.__ensureTemplatized()){return}this.__applyFullRefresh();this.__pool.length=0;this._setRenderedItemCount(this.__instances.length);this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}));this.__tryRenderChunk()}__applyFullRefresh(){let items=this.items||[];let isntIdxToItemsIdx=new Array(items.length);for(let i=0;i<items.length;i++){isntIdxToItemsIdx[i]=i}if(this.__filterFn){isntIdxToItemsIdx=isntIdxToItemsIdx.filter(((i,idx,array)=>this.__filterFn(items[i],idx,array)))}if(this.__sortFn){isntIdxToItemsIdx.sort(((a,b)=>this.__sortFn(items[a],items[b])))}const itemsIdxToInstIdx=this.__itemsIdxToInstIdx={};let instIdx=0;const limit=Math.min(isntIdxToItemsIdx.length,this.__limit);for(;instIdx<limit;instIdx++){let inst=this.__instances[instIdx];let itemIdx=isntIdxToItemsIdx[instIdx];let item=items[itemIdx];itemsIdxToInstIdx[itemIdx]=instIdx;if(inst){inst._setPendingProperty(this.as,item);inst._setPendingProperty(this.indexAs,instIdx);inst._setPendingProperty(this.itemsIndexAs,itemIdx);inst._flushProperties()}else{this.__insertInstance(item,instIdx,itemIdx)}}for(let i=this.__instances.length-1;i>=instIdx;i--){this.__detachAndRemoveInstance(i)}}__detachInstance(idx){let inst=this.__instances[idx];const wrappedRoot=wrap(inst.root);for(let i=0;i<inst.children.length;i++){let el=inst.children[i];wrappedRoot.appendChild(el)}return inst}__attachInstance(idx,parent){let inst=this.__instances[idx];parent.insertBefore(inst.root,this)}__detachAndRemoveInstance(idx){let inst=this.__detachInstance(idx);if(inst){this.__pool.push(inst)}this.__instances.splice(idx,1)}__stampInstance(item,instIdx,itemIdx){let model={};model[this.as]=item;model[this.indexAs]=instIdx;model[this.itemsIndexAs]=itemIdx;return new this.__ctor(model)}__insertInstance(item,instIdx,itemIdx){let inst=this.__pool.pop();if(inst){inst._setPendingProperty(this.as,item);inst._setPendingProperty(this.indexAs,instIdx);inst._setPendingProperty(this.itemsIndexAs,itemIdx);inst._flushProperties()}else{inst=this.__stampInstance(item,instIdx,itemIdx)}let beforeRow=this.__instances[instIdx+1];let beforeNode=beforeRow?beforeRow.children[0]:this;wrap(wrap(this).parentNode).insertBefore(inst.root,beforeNode);this.__instances[instIdx]=inst;return inst}_showHideChildren(hidden){for(let i=0;i<this.__instances.length;i++){this.__instances[i]._showHideChildren(hidden)}}__handleItemPath(path,value){let itemsPath=path.slice(6);let dot=itemsPath.indexOf(".");let itemsIdx=dot<0?itemsPath:itemsPath.substring(0,dot);if(itemsIdx==parseInt(itemsIdx,10)){let itemSubPath=dot<0?"":itemsPath.substring(dot+1);this.__handleObservedPaths(itemSubPath);let instIdx=this.__itemsIdxToInstIdx[itemsIdx];let inst=this.__instances[instIdx];if(inst){let itemPath=this.as+(itemSubPath?"."+itemSubPath:"");inst._setPendingPropertyOrPath(itemPath,value,false,true);inst._flushProperties()}return true}}itemForElement(el){let instance=this.modelForElement(el);return instance&&instance[this.as]}indexForElement(el){let instance=this.modelForElement(el);return instance&&instance[this.indexAs]}modelForElement(el){return modelForElement(this.template,el)}}customElements.define(DomRepeat.is,DomRepeat);const nativeShadow=!(window["ShadyDOM"]&&window["ShadyDOM"]["inUse"]);let nativeCssVariables_;function calcCssVariables(settings){if(settings&&settings["shimcssproperties"]){nativeCssVariables_=false}else{nativeCssVariables_=nativeShadow||Boolean(!navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)&&window.CSS&&CSS.supports&&CSS.supports("box-shadow","0 0 0 var(--foo)"))}}let cssBuild;if(window.ShadyCSS&&window.ShadyCSS.cssBuild!==undefined){cssBuild=window.ShadyCSS.cssBuild}const disableRuntime=Boolean(window.ShadyCSS&&window.ShadyCSS.disableRuntime);if(window.ShadyCSS&&window.ShadyCSS.nativeCss!==undefined){nativeCssVariables_=window.ShadyCSS.nativeCss}else if(window.ShadyCSS){calcCssVariables(window.ShadyCSS);window.ShadyCSS=undefined}else{calcCssVariables(window["WebComponents"]&&window["WebComponents"]["flags"])}const nativeCssVariables=nativeCssVariables_;class StyleNode{constructor(){this["start"]=0;this["end"]=0;this["previous"]=null;this["parent"]=null;this["rules"]=null;this["parsedCssText"]="";this["cssText"]="";this["atRule"]=false;this["type"]=0;this["keyframesName"]="";this["selector"]="";this["parsedSelector"]=""}}function parse(text){text=clean(text);return parseCss(lex(text),text)}function clean(cssText){return cssText.replace(RX.comments,"").replace(RX.port,"")}function lex(text){let root=new StyleNode;root["start"]=0;root["end"]=text.length;let n=root;for(let i=0,l=text.length;i<l;i++){if(text[i]===OPEN_BRACE){if(!n["rules"]){n["rules"]=[]}let p=n;let previous=p["rules"][p["rules"].length-1]||null;n=new StyleNode;n["start"]=i+1;n["parent"]=p;n["previous"]=previous;p["rules"].push(n)}else if(text[i]===CLOSE_BRACE){n["end"]=i+1;n=n["parent"]||root}}return root}function parseCss(node,text){let t=text.substring(node["start"],node["end"]-1);node["parsedCssText"]=node["cssText"]=t.trim();if(node["parent"]){let ss=node["previous"]?node["previous"]["end"]:node["parent"]["start"];t=text.substring(ss,node["start"]-1);t=_expandUnicodeEscapes(t);t=t.replace(RX.multipleSpaces," ");t=t.substring(t.lastIndexOf(";")+1);let s=node["parsedSelector"]=node["selector"]=t.trim();node["atRule"]=s.indexOf(AT_START)===0;if(node["atRule"]){if(s.indexOf(MEDIA_START)===0){node["type"]=types.MEDIA_RULE}else if(s.match(RX.keyframesRule)){node["type"]=types.KEYFRAMES_RULE;node["keyframesName"]=node["selector"].split(RX.multipleSpaces).pop()}}else{if(s.indexOf(VAR_START)===0){node["type"]=types.MIXIN_RULE}else{node["type"]=types.STYLE_RULE}}}let r$=node["rules"];if(r$){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){parseCss(r,text)}}return node}function _expandUnicodeEscapes(s){return s.replace(/\\([0-9a-f]{1,6})\s/gi,(function(){let code=arguments[1],repeat=6-code.length;while(repeat--){code="0"+code}return"\\"+code}))}function stringify(node,preserveProperties,text=""){let cssText="";if(node["cssText"]||node["rules"]){let r$=node["rules"];if(r$&&!_hasMixinRules(r$)){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){cssText=stringify(r,preserveProperties,cssText)}}else{cssText=preserveProperties?node["cssText"]:removeCustomProps(node["cssText"]);cssText=cssText.trim();if(cssText){cssText="  "+cssText+"\n"}}}if(cssText){if(node["selector"]){text+=node["selector"]+" "+OPEN_BRACE+"\n"}text+=cssText;if(node["selector"]){text+=CLOSE_BRACE+"\n\n"}}return text}function _hasMixinRules(rules){let r=rules[0];return Boolean(r)&&Boolean(r["selector"])&&r["selector"].indexOf(VAR_START)===0}function removeCustomProps(cssText){cssText=removeCustomPropAssignment(cssText);return removeCustomPropApply(cssText)}function removeCustomPropAssignment(cssText){return cssText.replace(RX.customProp,"").replace(RX.mixinProp,"")}function removeCustomPropApply(cssText){return cssText.replace(RX.mixinApply,"").replace(RX.varApply,"")}const types={STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1e3};const OPEN_BRACE="{";const CLOSE_BRACE="}";const RX={comments:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g};const VAR_START="--";const MEDIA_START="@media";const AT_START="@";const VAR_ASSIGN=/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};{])+)|\{([^}]*)\}(?:(?=[;\s}])|$))/gi;const MIXIN_MATCH=/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi;const MEDIA_MATCH=/@media\s(.*)/;const styleTextSet=new Set;const scopingAttribute="shady-unscoped";function processUnscopedStyle(style){const text=style.textContent;if(!styleTextSet.has(text)){styleTextSet.add(text);const newStyle=style.cloneNode(true);document.head.appendChild(newStyle)}}function isUnscopedStyle(style){return style.hasAttribute(scopingAttribute)}function toCssText(rules,callback){if(!rules){return""}if(typeof rules==="string"){rules=parse(rules)}if(callback){forEachRule(rules,callback)}return stringify(rules,nativeCssVariables)}function rulesForStyle(style){if(!style["__cssRules"]&&style.textContent){style["__cssRules"]=parse(style.textContent)}return style["__cssRules"]||null}function forEachRule(node,styleRuleCallback,keyframesRuleCallback,onlyActiveRules){if(!node){return}let skipRules=false;let type=node["type"];if(onlyActiveRules){if(type===types.MEDIA_RULE){let matchMedia=node["selector"].match(MEDIA_MATCH);if(matchMedia){if(!window.matchMedia(matchMedia[1]).matches){skipRules=true}}}}if(type===types.STYLE_RULE){styleRuleCallback(node)}else if(keyframesRuleCallback&&type===types.KEYFRAMES_RULE){keyframesRuleCallback(node)}else if(type===types.MIXIN_RULE){skipRules=true}let r$=node["rules"];if(r$&&!skipRules){for(let i=0,l=r$.length,r;i<l&&(r=r$[i]);i++){forEachRule(r,styleRuleCallback,keyframesRuleCallback,onlyActiveRules)}}}function findMatchingParen(text,start){let level=0;for(let i=start,l=text.length;i<l;i++){if(text[i]==="("){level++}else if(text[i]===")"){if(--level===0){return i}}}return-1}function processVariableAndFallback(str,callback){let start=str.indexOf("var(");if(start===-1){return callback(str,"","","")}let end=findMatchingParen(str,start+3);let inner=str.substring(start+4,end);let prefix=str.substring(0,start);let suffix=processVariableAndFallback(str.substring(end+1),callback);let comma=inner.indexOf(",");if(comma===-1){return callback(prefix,inner.trim(),"",suffix)}let value=inner.substring(0,comma).trim();let fallback=inner.substring(comma+1).trim();return callback(prefix,value,fallback,suffix)}window["ShadyDOM"]&&window["ShadyDOM"]["wrap"]||(node=>node);function getIsExtends(element){let localName=element["localName"];let is="",typeExtension="";if(localName){if(localName.indexOf("-")>-1){is=localName}else{typeExtension=localName;is=element.getAttribute&&element.getAttribute("is")||""}}else{is=element.is;typeExtension=element.extends}return{is:is,typeExtension:typeExtension}}function gatherStyleText(element){const styleTextParts=[];const styles=element.querySelectorAll("style");for(let i=0;i<styles.length;i++){const style=styles[i];if(isUnscopedStyle(style)){if(!nativeShadow){processUnscopedStyle(style);style.parentNode.removeChild(style)}}else{styleTextParts.push(style.textContent);style.parentNode.removeChild(style)}}return styleTextParts.join("").trim()}const CSS_BUILD_ATTR="css-build";function getCssBuild(element){if(cssBuild!==undefined){return cssBuild}if(element.__cssBuild===undefined){const attrValue=element.getAttribute(CSS_BUILD_ATTR);if(attrValue){element.__cssBuild=attrValue}else{const buildComment=getBuildComment(element);if(buildComment!==""){removeBuildComment(element)}element.__cssBuild=buildComment}}return element.__cssBuild||""}function elementHasBuiltCss(element){return getCssBuild(element)!==""}function getBuildComment(element){const buildComment=element.localName==="template"?element.content.firstChild:element.firstChild;if(buildComment instanceof Comment){const commentParts=buildComment.textContent.trim().split(":");if(commentParts[0]===CSS_BUILD_ATTR){return commentParts[1]}}return""}function removeBuildComment(element){const buildComment=element.localName==="template"?element.content.firstChild:element.firstChild;buildComment.parentNode.removeChild(buildComment)}function updateNativeProperties(element,properties){for(let p in properties){if(p===null){element.style.removeProperty(p)}else{element.style.setProperty(p,properties[p])}}}function getComputedStyleValue(element,property){const value=window.getComputedStyle(element).getPropertyValue(property);if(!value){return""}else{return value.trim()}}function detectMixin(cssText){const has=MIXIN_MATCH.test(cssText)||VAR_ASSIGN.test(cssText);MIXIN_MATCH.lastIndex=0;VAR_ASSIGN.lastIndex=0;return has}const APPLY_NAME_CLEAN=/;\s*/m;const INITIAL_INHERIT=/^\s*(initial)|(inherit)\s*$/;const IMPORTANT=/\s*!important/;const MIXIN_VAR_SEP="_-_";class MixinMap{constructor(){this._map={}}set(name,props){name=name.trim();this._map[name]={properties:props,dependants:{}}}get(name){name=name.trim();return this._map[name]||null}}let invalidCallback=null;class ApplyShim{constructor(){this._currentElement=null;this._measureElement=null;this._map=new MixinMap}detectMixin(cssText){return detectMixin(cssText)}gatherStyles(template){const styleText=gatherStyleText(template.content);if(styleText){const style=document.createElement("style");style.textContent=styleText;template.content.insertBefore(style,template.content.firstChild);return style}return null}transformTemplate(template,elementName){if(template._gatheredStyle===undefined){template._gatheredStyle=this.gatherStyles(template)}const style=template._gatheredStyle;return style?this.transformStyle(style,elementName):null}transformStyle(style,elementName=""){let ast=rulesForStyle(style);this.transformRules(ast,elementName);style.textContent=toCssText(ast);return ast}transformCustomStyle(style){let ast=rulesForStyle(style);forEachRule(ast,(rule=>{if(rule["selector"]===":root"){rule["selector"]="html"}this.transformRule(rule)}));style.textContent=toCssText(ast);return ast}transformRules(rules,elementName){this._currentElement=elementName;forEachRule(rules,(r=>{this.transformRule(r)}));this._currentElement=null}transformRule(rule){rule["cssText"]=this.transformCssText(rule["parsedCssText"],rule);if(rule["selector"]===":root"){rule["selector"]=":host > *"}}transformCssText(cssText,rule){cssText=cssText.replace(VAR_ASSIGN,((matchText,propertyName,valueProperty,valueMixin)=>this._produceCssProperties(matchText,propertyName,valueProperty,valueMixin,rule)));return this._consumeCssProperties(cssText,rule)}_getInitialValueForProperty(property){if(!this._measureElement){this._measureElement=document.createElement("meta");this._measureElement.setAttribute("apply-shim-measure","");this._measureElement.style.all="initial";document.head.appendChild(this._measureElement)}return window.getComputedStyle(this._measureElement).getPropertyValue(property)}_fallbacksFromPreviousRules(startRule){let topRule=startRule;while(topRule["parent"]){topRule=topRule["parent"]}const fallbacks={};let seenStartRule=false;forEachRule(topRule,(r=>{seenStartRule=seenStartRule||r===startRule;if(seenStartRule){return}if(r["selector"]===startRule["selector"]){Object.assign(fallbacks,this._cssTextToMap(r["parsedCssText"]))}}));return fallbacks}_consumeCssProperties(text,rule){let m=null;while(m=MIXIN_MATCH.exec(text)){let matchText=m[0];let mixinName=m[1];let idx=m.index;let applyPos=idx+matchText.indexOf("@apply");let afterApplyPos=idx+matchText.length;let textBeforeApply=text.slice(0,applyPos);let textAfterApply=text.slice(afterApplyPos);let defaults=rule?this._fallbacksFromPreviousRules(rule):{};Object.assign(defaults,this._cssTextToMap(textBeforeApply));let replacement=this._atApplyToCssProperties(mixinName,defaults);text=`${textBeforeApply}${replacement}${textAfterApply}`;MIXIN_MATCH.lastIndex=idx+replacement.length}return text}_atApplyToCssProperties(mixinName,fallbacks){mixinName=mixinName.replace(APPLY_NAME_CLEAN,"");let vars=[];let mixinEntry=this._map.get(mixinName);if(!mixinEntry){this._map.set(mixinName,{});mixinEntry=this._map.get(mixinName)}if(mixinEntry){if(this._currentElement){mixinEntry.dependants[this._currentElement]=true}let p,parts,f;const properties=mixinEntry.properties;for(p in properties){f=fallbacks&&fallbacks[p];parts=[p,": var(",mixinName,MIXIN_VAR_SEP,p];if(f){parts.push(",",f.replace(IMPORTANT,""))}parts.push(")");if(IMPORTANT.test(properties[p])){parts.push(" !important")}vars.push(parts.join(""))}}return vars.join("; ")}_replaceInitialOrInherit(property,value){let match=INITIAL_INHERIT.exec(value);if(match){if(match[1]){value=this._getInitialValueForProperty(property)}else{value="apply-shim-inherit"}}return value}_cssTextToMap(text,replaceInitialOrInherit=false){let props=text.split(";");let property,value;let out={};for(let i=0,p,sp;i<props.length;i++){p=props[i];if(p){sp=p.split(":");if(sp.length>1){property=sp[0].trim();value=sp.slice(1).join(":");if(replaceInitialOrInherit){value=this._replaceInitialOrInherit(property,value)}out[property]=value}}}return out}_invalidateMixinEntry(mixinEntry){if(!invalidCallback){return}for(let elementName in mixinEntry.dependants){if(elementName!==this._currentElement){invalidCallback(elementName)}}}_produceCssProperties(matchText,propertyName,valueProperty,valueMixin,rule){if(valueProperty){processVariableAndFallback(valueProperty,((prefix,value)=>{if(value&&this._map.get(value)){valueMixin=`@apply ${value};`}}))}if(!valueMixin){return matchText}let mixinAsProperties=this._consumeCssProperties(""+valueMixin,rule);let prefix=matchText.slice(0,matchText.indexOf("--"));let mixinValues=this._cssTextToMap(mixinAsProperties,true);let combinedProps=mixinValues;let mixinEntry=this._map.get(propertyName);let oldProps=mixinEntry&&mixinEntry.properties;if(oldProps){combinedProps=Object.assign(Object.create(oldProps),mixinValues)}else{this._map.set(propertyName,combinedProps)}let out=[];let p,v;let needToInvalidate=false;for(p in combinedProps){v=mixinValues[p];if(v===undefined){v="initial"}if(oldProps&&!(p in oldProps)){needToInvalidate=true}out.push(`${propertyName}${MIXIN_VAR_SEP}${p}: ${v}`)}if(needToInvalidate){this._invalidateMixinEntry(mixinEntry)}if(mixinEntry){mixinEntry.properties=combinedProps}if(valueProperty){prefix=`${matchText};${prefix}`}return`${prefix}${out.join("; ")};`}}ApplyShim.prototype["detectMixin"]=ApplyShim.prototype.detectMixin;ApplyShim.prototype["transformStyle"]=ApplyShim.prototype.transformStyle;ApplyShim.prototype["transformCustomStyle"]=ApplyShim.prototype.transformCustomStyle;ApplyShim.prototype["transformRules"]=ApplyShim.prototype.transformRules;ApplyShim.prototype["transformRule"]=ApplyShim.prototype.transformRule;ApplyShim.prototype["transformTemplate"]=ApplyShim.prototype.transformTemplate;ApplyShim.prototype["_separator"]=MIXIN_VAR_SEP;Object.defineProperty(ApplyShim.prototype,"invalidCallback",{get(){return invalidCallback},set(cb){invalidCallback=cb}});const templateMap={};const CURRENT_VERSION="_applyShimCurrentVersion";const NEXT_VERSION="_applyShimNextVersion";const VALIDATING_VERSION="_applyShimValidatingVersion";const promise=Promise.resolve();function invalidate(elementName){let template=templateMap[elementName];if(template){invalidateTemplate(template)}}function invalidateTemplate(template){template[CURRENT_VERSION]=template[CURRENT_VERSION]||0;template[VALIDATING_VERSION]=template[VALIDATING_VERSION]||0;template[NEXT_VERSION]=(template[NEXT_VERSION]||0)+1}function templateIsValid(template){return template[CURRENT_VERSION]===template[NEXT_VERSION]}function templateIsValidating(template){return!templateIsValid(template)&&template[VALIDATING_VERSION]===template[NEXT_VERSION]}function startValidatingTemplate(template){template[VALIDATING_VERSION]=template[NEXT_VERSION];if(!template._validating){template._validating=true;promise.then((function(){template[CURRENT_VERSION]=template[NEXT_VERSION];template._validating=false}))}}let readyPromise=null;let whenReady=window["HTMLImports"]&&window["HTMLImports"]["whenReady"]||null;let resolveFn;function documentWait(callback){requestAnimationFrame((function(){if(whenReady){whenReady(callback)}else{if(!readyPromise){readyPromise=new Promise((resolve=>{resolveFn=resolve}));if(document.readyState==="complete"){resolveFn()}else{document.addEventListener("readystatechange",(()=>{if(document.readyState==="complete"){resolveFn()}}))}}readyPromise.then((function(){callback&&callback()}))}}))}const SEEN_MARKER="__seenByShadyCSS";const CACHED_STYLE="__shadyCSSCachedStyle";let transformFn=null;let validateFn=null;class CustomStyleInterface$1{constructor(){this["customStyles"]=[];this["enqueued"]=false;documentWait((()=>{if(window["ShadyCSS"]["flushCustomStyles"]){window["ShadyCSS"]["flushCustomStyles"]()}}))}enqueueDocumentValidation(){if(this["enqueued"]||!validateFn){return}this["enqueued"]=true;documentWait(validateFn)}addCustomStyle(style){if(!style[SEEN_MARKER]){style[SEEN_MARKER]=true;this["customStyles"].push(style);this.enqueueDocumentValidation()}}getStyleForCustomStyle(customStyle){if(customStyle[CACHED_STYLE]){return customStyle[CACHED_STYLE]}let style;if(customStyle["getStyle"]){style=customStyle["getStyle"]()}else{style=customStyle}return style}processStyles(){const cs=this["customStyles"];for(let i=0;i<cs.length;i++){const customStyle=cs[i];if(customStyle[CACHED_STYLE]){continue}const style=this.getStyleForCustomStyle(customStyle);if(style){const styleToTransform=style["__appliedElement"]||style;if(transformFn){transformFn(styleToTransform)}customStyle[CACHED_STYLE]=styleToTransform}}return cs}}CustomStyleInterface$1.prototype["addCustomStyle"]=CustomStyleInterface$1.prototype.addCustomStyle;CustomStyleInterface$1.prototype["getStyleForCustomStyle"]=CustomStyleInterface$1.prototype.getStyleForCustomStyle;CustomStyleInterface$1.prototype["processStyles"]=CustomStyleInterface$1.prototype.processStyles;Object.defineProperties(CustomStyleInterface$1.prototype,{transformCallback:{get(){return transformFn},set(fn){transformFn=fn}},validateCallback:{get(){return validateFn},set(fn){let needsEnqueue=false;if(!validateFn){needsEnqueue=true}validateFn=fn;if(needsEnqueue){this.enqueueDocumentValidation()}}}});const applyShim=new ApplyShim;class ApplyShimInterface{constructor(){this.customStyleInterface=null;applyShim["invalidCallback"]=invalidate}ensure(){if(this.customStyleInterface){return}if(window.ShadyCSS.CustomStyleInterface){this.customStyleInterface=window.ShadyCSS.CustomStyleInterface;this.customStyleInterface["transformCallback"]=style=>{applyShim.transformCustomStyle(style)};this.customStyleInterface["validateCallback"]=()=>{requestAnimationFrame((()=>{if(this.customStyleInterface["enqueued"]){this.flushCustomStyles()}}))}}}prepareTemplate(template,elementName){this.ensure();if(elementHasBuiltCss(template)){return}templateMap[elementName]=template;let ast=applyShim.transformTemplate(template,elementName);template["_styleAst"]=ast}flushCustomStyles(){this.ensure();if(!this.customStyleInterface){return}let styles=this.customStyleInterface["processStyles"]();if(!this.customStyleInterface["enqueued"]){return}for(let i=0;i<styles.length;i++){let cs=styles[i];let style=this.customStyleInterface["getStyleForCustomStyle"](cs);if(style){applyShim.transformCustomStyle(style)}}this.customStyleInterface["enqueued"]=false}styleSubtree(element,properties){this.ensure();if(properties){updateNativeProperties(element,properties)}if(element.shadowRoot){this.styleElement(element);let shadowChildren=element.shadowRoot.children||element.shadowRoot.childNodes;for(let i=0;i<shadowChildren.length;i++){this.styleSubtree(shadowChildren[i])}}else{let children=element.children||element.childNodes;for(let i=0;i<children.length;i++){this.styleSubtree(children[i])}}}styleElement(element){this.ensure();let{is:is}=getIsExtends(element);let template=templateMap[is];if(template&&elementHasBuiltCss(template)){return}if(template&&!templateIsValid(template)){if(!templateIsValidating(template)){this.prepareTemplate(template,is);startValidatingTemplate(template)}let root=element.shadowRoot;if(root){let style=root.querySelector("style");if(style){style["__cssRules"]=template["_styleAst"];style.textContent=toCssText(template["_styleAst"])}}}}styleDocument(properties){this.ensure();this.styleSubtree(document.body,properties)}}if(!window.ShadyCSS||!window.ShadyCSS.ScopingShim){const applyShimInterface=new ApplyShimInterface;let CustomStyleInterface=window.ShadyCSS&&window.ShadyCSS.CustomStyleInterface;window.ShadyCSS={prepareTemplate(template,elementName,elementExtends){applyShimInterface.flushCustomStyles();applyShimInterface.prepareTemplate(template,elementName)},prepareTemplateStyles(template,elementName,elementExtends){window.ShadyCSS.prepareTemplate(template,elementName,elementExtends)},prepareTemplateDom(template,elementName){},styleSubtree(element,properties){applyShimInterface.flushCustomStyles();applyShimInterface.styleSubtree(element,properties)},styleElement(element){applyShimInterface.flushCustomStyles();applyShimInterface.styleElement(element)},styleDocument(properties){applyShimInterface.flushCustomStyles();applyShimInterface.styleDocument(properties)},getComputedStyleValue(element,property){return getComputedStyleValue(element,property)},flushCustomStyles(){applyShimInterface.flushCustomStyles()},nativeCss:nativeCssVariables,nativeShadow:nativeShadow,cssBuild:cssBuild,disableRuntime:disableRuntime};if(CustomStyleInterface){window.ShadyCSS.CustomStyleInterface=CustomStyleInterface}}window.ShadyCSS.ApplyShim=applyShim;const GestureEventListeners=dedupingMixin((superClass=>{class GestureEventListeners extends superClass{_addEventListenerToNode(node,eventName,handler){if(!addListener(node,eventName,handler)){super._addEventListenerToNode(node,eventName,handler)}}_removeEventListenerFromNode(node,eventName,handler){if(!removeListener(node,eventName,handler)){super._removeEventListenerFromNode(node,eventName,handler)}}}return GestureEventListeners}));let scheduled=false;let beforeRenderQueue=[];let afterRenderQueue=[];function schedule(){scheduled=true;requestAnimationFrame((function(){scheduled=false;flushQueue(beforeRenderQueue);setTimeout((function(){runQueue(afterRenderQueue)}))}))}function flushQueue(queue){while(queue.length){callMethod(queue.shift())}}function runQueue(queue){for(let i=0,l=queue.length;i<l;i++){callMethod(queue.shift())}}function callMethod(info){const context=info[0];const callback=info[1];const args=info[2];try{callback.apply(context,args)}catch(e){setTimeout((()=>{throw e}))}}function beforeNextRender(context,callback,args){if(!scheduled){schedule()}beforeRenderQueue.push([context,callback,args])}function afterNextRender(context,callback,args){if(!scheduled){schedule()}afterRenderQueue.push([context,callback,args])}function resolve(){document.body.removeAttribute("unresolved")}if(document.readyState==="interactive"||document.readyState==="complete"){resolve()}else{window.addEventListener("DOMContentLoaded",resolve)}function newSplice(index,removed,addedCount){return{index:index,removed:removed,addedCount:addedCount}}const EDIT_LEAVE=0;const EDIT_UPDATE=1;const EDIT_ADD=2;const EDIT_DELETE=3;function calcEditDistances(current,currentStart,currentEnd,old,oldStart,oldEnd){let rowCount=oldEnd-oldStart+1;let columnCount=currentEnd-currentStart+1;let distances=new Array(rowCount);for(let i=0;i<rowCount;i++){distances[i]=new Array(columnCount);distances[i][0]=i}for(let j=0;j<columnCount;j++)distances[0][j]=j;for(let i=1;i<rowCount;i++){for(let j=1;j<columnCount;j++){if(equals(current[currentStart+j-1],old[oldStart+i-1]))distances[i][j]=distances[i-1][j-1];else{let north=distances[i-1][j]+1;let west=distances[i][j-1]+1;distances[i][j]=north<west?north:west}}}return distances}function spliceOperationsFromEditDistances(distances){let i=distances.length-1;let j=distances[0].length-1;let current=distances[i][j];let edits=[];while(i>0||j>0){if(i==0){edits.push(EDIT_ADD);j--;continue}if(j==0){edits.push(EDIT_DELETE);i--;continue}let northWest=distances[i-1][j-1];let west=distances[i-1][j];let north=distances[i][j-1];let min;if(west<north)min=west<northWest?west:northWest;else min=north<northWest?north:northWest;if(min==northWest){if(northWest==current){edits.push(EDIT_LEAVE)}else{edits.push(EDIT_UPDATE);current=northWest}i--;j--}else if(min==west){edits.push(EDIT_DELETE);i--;current=west}else{edits.push(EDIT_ADD);j--;current=north}}edits.reverse();return edits}function calcSplices(current,currentStart,currentEnd,old,oldStart,oldEnd){let prefixCount=0;let suffixCount=0;let splice;let minLength=Math.min(currentEnd-currentStart,oldEnd-oldStart);if(currentStart==0&&oldStart==0)prefixCount=sharedPrefix(current,old,minLength);if(currentEnd==current.length&&oldEnd==old.length)suffixCount=sharedSuffix(current,old,minLength-prefixCount);currentStart+=prefixCount;oldStart+=prefixCount;currentEnd-=suffixCount;oldEnd-=suffixCount;if(currentEnd-currentStart==0&&oldEnd-oldStart==0)return[];if(currentStart==currentEnd){splice=newSplice(currentStart,[],0);while(oldStart<oldEnd)splice.removed.push(old[oldStart++]);return[splice]}else if(oldStart==oldEnd)return[newSplice(currentStart,[],currentEnd-currentStart)];let ops=spliceOperationsFromEditDistances(calcEditDistances(current,currentStart,currentEnd,old,oldStart,oldEnd));splice=undefined;let splices=[];let index=currentStart;let oldIndex=oldStart;for(let i=0;i<ops.length;i++){switch(ops[i]){case EDIT_LEAVE:if(splice){splices.push(splice);splice=undefined}index++;oldIndex++;break;case EDIT_UPDATE:if(!splice)splice=newSplice(index,[],0);splice.addedCount++;index++;splice.removed.push(old[oldIndex]);oldIndex++;break;case EDIT_ADD:if(!splice)splice=newSplice(index,[],0);splice.addedCount++;index++;break;case EDIT_DELETE:if(!splice)splice=newSplice(index,[],0);splice.removed.push(old[oldIndex]);oldIndex++;break}}if(splice){splices.push(splice)}return splices}function sharedPrefix(current,old,searchLength){for(let i=0;i<searchLength;i++)if(!equals(current[i],old[i]))return i;return searchLength}function sharedSuffix(current,old,searchLength){let index1=current.length;let index2=old.length;let count=0;while(count<searchLength&&equals(current[--index1],old[--index2]))count++;return count}function calculateSplices(current,previous){return calcSplices(current,0,current.length,previous,0,previous.length)}function equals(currentValue,previousValue){return currentValue===previousValue}function isSlot(node){return node.localName==="slot"}let FlattenedNodesObserver=class{static getFlattenedNodes(node){const wrapped=wrap(node);if(isSlot(node)){node=node;return wrapped.assignedNodes({flatten:true})}else{return Array.from(wrapped.childNodes).map((node=>{if(isSlot(node)){node=node;return wrap(node).assignedNodes({flatten:true})}else{return[node]}})).reduce(((a,b)=>a.concat(b)),[])}}constructor(target,callback){this._shadyChildrenObserver=null;this._nativeChildrenObserver=null;this._connected=false;this._target=target;this.callback=callback;this._effectiveNodes=[];this._observer=null;this._scheduled=false;this._boundSchedule=()=>{this._schedule()};this.connect();this._schedule()}connect(){if(isSlot(this._target)){this._listenSlots([this._target])}else if(wrap(this._target).children){this._listenSlots(wrap(this._target).children);if(window.ShadyDOM){this._shadyChildrenObserver=ShadyDOM.observeChildren(this._target,(mutations=>{this._processMutations(mutations)}))}else{this._nativeChildrenObserver=new MutationObserver((mutations=>{this._processMutations(mutations)}));this._nativeChildrenObserver.observe(this._target,{childList:true})}}this._connected=true}disconnect(){if(isSlot(this._target)){this._unlistenSlots([this._target])}else if(wrap(this._target).children){this._unlistenSlots(wrap(this._target).children);if(window.ShadyDOM&&this._shadyChildrenObserver){ShadyDOM.unobserveChildren(this._shadyChildrenObserver);this._shadyChildrenObserver=null}else if(this._nativeChildrenObserver){this._nativeChildrenObserver.disconnect();this._nativeChildrenObserver=null}}this._connected=false}_schedule(){if(!this._scheduled){this._scheduled=true;microTask.run((()=>this.flush()))}}_processMutations(mutations){this._processSlotMutations(mutations);this.flush()}_processSlotMutations(mutations){if(mutations){for(let i=0;i<mutations.length;i++){let mutation=mutations[i];if(mutation.addedNodes){this._listenSlots(mutation.addedNodes)}if(mutation.removedNodes){this._unlistenSlots(mutation.removedNodes)}}}}flush(){if(!this._connected){return false}if(window.ShadyDOM){ShadyDOM.flush()}if(this._nativeChildrenObserver){this._processSlotMutations(this._nativeChildrenObserver.takeRecords())}else if(this._shadyChildrenObserver){this._processSlotMutations(this._shadyChildrenObserver.takeRecords())}this._scheduled=false;let info={target:this._target,addedNodes:[],removedNodes:[]};let newNodes=this.constructor.getFlattenedNodes(this._target);let splices=calculateSplices(newNodes,this._effectiveNodes);for(let i=0,s;i<splices.length&&(s=splices[i]);i++){for(let j=0,n;j<s.removed.length&&(n=s.removed[j]);j++){info.removedNodes.push(n)}}for(let i=0,s;i<splices.length&&(s=splices[i]);i++){for(let j=s.index;j<s.index+s.addedCount;j++){info.addedNodes.push(newNodes[j])}}this._effectiveNodes=newNodes;let didFlush=false;if(info.addedNodes.length||info.removedNodes.length){didFlush=true;this.callback.call(this._target,info)}return didFlush}_listenSlots(nodeList){for(let i=0;i<nodeList.length;i++){let n=nodeList[i];if(isSlot(n)){n.addEventListener("slotchange",this._boundSchedule)}}}_unlistenSlots(nodeList){for(let i=0;i<nodeList.length;i++){let n=nodeList[i];if(isSlot(n)){n.removeEventListener("slotchange",this._boundSchedule)}}}};const p=Element.prototype;const normalizedMatchesSelector=p.matches||p.matchesSelector||p.mozMatchesSelector||p.msMatchesSelector||p.oMatchesSelector||p.webkitMatchesSelector;const matchesSelector=function(node,selector){return normalizedMatchesSelector.call(node,selector)};class DomApiNative{constructor(node){this.node=node}observeNodes(callback){return new FlattenedNodesObserver(this.node,callback)}unobserveNodes(observerHandle){observerHandle.disconnect()}notifyObserver(){}deepContains(node){if(wrap(this.node).contains(node)){return true}let n=node;let doc=node.ownerDocument;while(n&&n!==doc&&n!==this.node){n=wrap(n).parentNode||wrap(n).host}return n===this.node}getOwnerRoot(){return wrap(this.node).getRootNode()}getDistributedNodes(){return this.node.localName==="slot"?wrap(this.node).assignedNodes({flatten:true}):[]}getDestinationInsertionPoints(){let ip$=[];let n=wrap(this.node).assignedSlot;while(n){ip$.push(n);n=wrap(n).assignedSlot}return ip$}importNode(node,deep){let doc=this.node instanceof Document?this.node:this.node.ownerDocument;return wrap(doc).importNode(node,deep)}getEffectiveChildNodes(){return FlattenedNodesObserver.getFlattenedNodes(this.node)}queryDistributedElements(selector){let c$=this.getEffectiveChildNodes();let list=[];for(let i=0,l=c$.length,c;i<l&&(c=c$[i]);i++){if(c.nodeType===Node.ELEMENT_NODE&&matchesSelector(c,selector)){list.push(c)}}return list}get activeElement(){let node=this.node;return node._activeElement!==undefined?node._activeElement:node.activeElement}}function forwardMethods(proto,methods){for(let i=0;i<methods.length;i++){let method=methods[i];proto[method]=function(){return this.node[method].apply(this.node,arguments)}}}function forwardReadOnlyProperties(proto,properties){for(let i=0;i<properties.length;i++){let name=properties[i];Object.defineProperty(proto,name,{get:function(){const domApi=this;return domApi.node[name]},configurable:true})}}function forwardProperties(proto,properties){for(let i=0;i<properties.length;i++){let name=properties[i];Object.defineProperty(proto,name,{get:function(){return this.node[name]},set:function(value){this.node[name]=value},configurable:true})}}class EventApi{constructor(event){this.event=event}get rootTarget(){return this.path[0]}get localTarget(){return this.event.target}get path(){return this.event.composedPath()}}DomApiNative.prototype.cloneNode;DomApiNative.prototype.appendChild;DomApiNative.prototype.insertBefore;DomApiNative.prototype.removeChild;DomApiNative.prototype.replaceChild;DomApiNative.prototype.setAttribute;DomApiNative.prototype.removeAttribute;DomApiNative.prototype.querySelector;DomApiNative.prototype.querySelectorAll;DomApiNative.prototype.parentNode;DomApiNative.prototype.firstChild;DomApiNative.prototype.lastChild;DomApiNative.prototype.nextSibling;DomApiNative.prototype.previousSibling;DomApiNative.prototype.firstElementChild;DomApiNative.prototype.lastElementChild;DomApiNative.prototype.nextElementSibling;DomApiNative.prototype.previousElementSibling;DomApiNative.prototype.childNodes;DomApiNative.prototype.children;DomApiNative.prototype.classList;DomApiNative.prototype.textContent;DomApiNative.prototype.innerHTML;let DomApiImpl=DomApiNative;if(window["ShadyDOM"]&&window["ShadyDOM"]["inUse"]&&window["ShadyDOM"]["noPatch"]&&window["ShadyDOM"]["Wrapper"]){class Wrapper extends window["ShadyDOM"]["Wrapper"]{}Object.getOwnPropertyNames(DomApiNative.prototype).forEach((prop=>{if(prop!="activeElement"){Wrapper.prototype[prop]=DomApiNative.prototype[prop]}}));forwardReadOnlyProperties(Wrapper.prototype,["classList"]);DomApiImpl=Wrapper;Object.defineProperties(EventApi.prototype,{localTarget:{get(){return this.event.currentTarget},configurable:true},path:{get(){return window["ShadyDOM"]["composedPath"](this.event)},configurable:true}})}else{forwardMethods(DomApiNative.prototype,["cloneNode","appendChild","insertBefore","removeChild","replaceChild","setAttribute","removeAttribute","querySelector","querySelectorAll"]);forwardReadOnlyProperties(DomApiNative.prototype,["parentNode","firstChild","lastChild","nextSibling","previousSibling","firstElementChild","lastElementChild","nextElementSibling","previousElementSibling","childNodes","children","classList"]);forwardProperties(DomApiNative.prototype,["textContent","innerHTML"])}const dom=function(obj){obj=obj||document;if(obj instanceof DomApiImpl){return obj}if(obj instanceof EventApi){return obj}let helper=obj["__domApi"];if(!helper){if(obj instanceof Event){helper=new EventApi(obj)}else{helper=new DomApiImpl(obj)}obj["__domApi"]=helper}return helper};let styleInterface=window.ShadyCSS;const LegacyElementMixin=dedupingMixin((base=>{const legacyElementBase=GestureEventListeners(ElementMixin(base));const DIRECTION_MAP={x:"pan-x",y:"pan-y",none:"none",all:"auto"};class LegacyElement extends legacyElementBase{constructor(){super();this.isAttached;this.__boundListeners;this._debouncers}static get importMeta(){return this.prototype.importMeta}created(){}connectedCallback(){super.connectedCallback();this.isAttached=true;this.attached()}attached(){}disconnectedCallback(){super.disconnectedCallback();this.isAttached=false;this.detached()}detached(){}attributeChangedCallback(name,old,value,namespace){if(old!==value){super.attributeChangedCallback(name,old,value,namespace);this.attributeChanged(name,old,value)}}attributeChanged(name,old,value){}_initializeProperties(){let proto=Object.getPrototypeOf(this);if(!proto.hasOwnProperty("__hasRegisterFinished")){this._registered();proto.__hasRegisterFinished=true}super._initializeProperties();this.root=this;this.created();this._applyListeners()}_registered(){}ready(){this._ensureAttributes();super.ready()}_ensureAttributes(){}_applyListeners(){}serialize(value){return this._serializeValue(value)}deserialize(value,type){return this._deserializeValue(value,type)}reflectPropertyToAttribute(property,attribute,value){this._propertyToAttribute(property,attribute,value)}serializeValueToAttribute(value,attribute,node){this._valueToNodeAttribute(node||this,value,attribute)}extend(prototype,api){if(!(prototype&&api)){return prototype||api}let n$=Object.getOwnPropertyNames(api);for(let i=0,n;i<n$.length&&(n=n$[i]);i++){let pd=Object.getOwnPropertyDescriptor(api,n);if(pd){Object.defineProperty(prototype,n,pd)}}return prototype}mixin(target,source){for(let i in source){target[i]=source[i]}return target}chainObject(object,prototype){if(object&&prototype&&object!==prototype){object.__proto__=prototype}return object}instanceTemplate(template){let content=this.constructor._contentForTemplate(template);let dom=document.importNode(content,true);return dom}fire(type,detail,options){options=options||{};detail=detail===null||detail===undefined?{}:detail;let event=new Event(type,{bubbles:options.bubbles===undefined?true:options.bubbles,cancelable:Boolean(options.cancelable),composed:options.composed===undefined?true:options.composed});event.detail=detail;let node=options.node||this;wrap(node).dispatchEvent(event);return event}listen(node,eventName,methodName){node=node||this;let hbl=this.__boundListeners||(this.__boundListeners=new WeakMap);let bl=hbl.get(node);if(!bl){bl={};hbl.set(node,bl)}let key=eventName+methodName;if(!bl[key]){bl[key]=this._addMethodEventListenerToNode(node,eventName,methodName,this)}}unlisten(node,eventName,methodName){node=node||this;let bl=this.__boundListeners&&this.__boundListeners.get(node);let key=eventName+methodName;let handler=bl&&bl[key];if(handler){this._removeEventListenerFromNode(node,eventName,handler);bl[key]=null}}setScrollDirection(direction,node){setTouchAction(node||this,DIRECTION_MAP[direction]||"auto")}$$(slctr){return this.root.querySelector(slctr)}get domHost(){let root=wrap(this).getRootNode();return root instanceof DocumentFragment?root.host:root}distributeContent(){const thisEl=this;const domApi=dom(thisEl);if(window.ShadyDOM&&domApi.shadowRoot){ShadyDOM.flush()}}getEffectiveChildNodes(){const thisEl=this;const domApi=dom(thisEl);return domApi.getEffectiveChildNodes()}queryDistributedElements(selector){const thisEl=this;const domApi=dom(thisEl);return domApi.queryDistributedElements(selector)}getEffectiveChildren(){let list=this.getEffectiveChildNodes();return list.filter((function(n){return n.nodeType===Node.ELEMENT_NODE}))}getEffectiveTextContent(){let cn=this.getEffectiveChildNodes();let tc=[];for(let i=0,c;c=cn[i];i++){if(c.nodeType!==Node.COMMENT_NODE){tc.push(c.textContent)}}return tc.join("")}queryEffectiveChildren(selector){let e$=this.queryDistributedElements(selector);return e$&&e$[0]}queryAllEffectiveChildren(selector){return this.queryDistributedElements(selector)}getContentChildNodes(slctr){let content=this.root.querySelector(slctr||"slot");return content?dom(content).getDistributedNodes():[]}getContentChildren(slctr){let children=this.getContentChildNodes(slctr).filter((function(n){return n.nodeType===Node.ELEMENT_NODE}));return children}isLightDescendant(node){const thisNode=this;return thisNode!==node&&wrap(thisNode).contains(node)&&wrap(thisNode).getRootNode()===wrap(node).getRootNode()}isLocalDescendant(node){return this.root===wrap(node).getRootNode()}scopeSubtree(container,shouldObserve){}getComputedStyleValue(property){return styleInterface.getComputedStyleValue(this,property)}debounce(jobName,callback,wait){this._debouncers=this._debouncers||{};return this._debouncers[jobName]=Debouncer.debounce(this._debouncers[jobName],wait>0?timeOut.after(wait):microTask,callback.bind(this))}isDebouncerActive(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];return!!(debouncer&&debouncer.isActive())}flushDebouncer(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];if(debouncer){debouncer.flush()}}cancelDebouncer(jobName){this._debouncers=this._debouncers||{};let debouncer=this._debouncers[jobName];if(debouncer){debouncer.cancel()}}async(callback,waitTime){return waitTime>0?timeOut.run(callback.bind(this),waitTime):~microTask.run(callback.bind(this))}cancelAsync(handle){handle<0?microTask.cancel(~handle):timeOut.cancel(handle)}create(tag,props){let elt=document.createElement(tag);if(props){if(elt.setProperties){elt.setProperties(props)}else{for(let n in props){elt[n]=props[n]}}}return elt}elementMatches(selector,node){return matchesSelector(node||this,selector)}toggleAttribute(name,bool){let node=this;if(arguments.length===3){node=arguments[2]}if(arguments.length==1){bool=!node.hasAttribute(name)}if(bool){wrap(node).setAttribute(name,"");return true}else{wrap(node).removeAttribute(name);return false}}toggleClass(name,bool,node){node=node||this;if(arguments.length==1){bool=!node.classList.contains(name)}if(bool){node.classList.add(name)}else{node.classList.remove(name)}}transform(transformText,node){node=node||this;node.style.webkitTransform=transformText;node.style.transform=transformText}translate3d(x,y,z,node){node=node||this;this.transform("translate3d("+x+","+y+","+z+")",node)}arrayDelete(arrayOrPath,item){let index;if(Array.isArray(arrayOrPath)){index=arrayOrPath.indexOf(item);if(index>=0){return arrayOrPath.splice(index,1)}}else{let arr=get(this,arrayOrPath);index=arr.indexOf(item);if(index>=0){return this.splice(arrayOrPath,index,1)}}return null}_logger(level,args){if(Array.isArray(args)&&args.length===1&&Array.isArray(args[0])){args=args[0]}switch(level){case"log":case"warn":case"error":console[level](...args)}}_log(...args){this._logger("log",args)}_warn(...args){this._logger("warn",args)}_error(...args){this._logger("error",args)}_logf(methodName,...args){return["[%s::%s]",this.is,methodName,...args]}}LegacyElement.prototype.is="";return LegacyElement}));const lifecycleProps={attached:true,detached:true,ready:true,created:true,beforeRegister:true,registered:true,attributeChanged:true,listeners:true,hostAttributes:true};const excludeOnInfo={attached:true,detached:true,ready:true,created:true,beforeRegister:true,registered:true,attributeChanged:true,behaviors:true,_noAccessors:true};const excludeOnBehaviors=Object.assign({listeners:true,hostAttributes:true,properties:true,observers:true},excludeOnInfo);function copyProperties(source,target,excludeProps){const noAccessors=source._noAccessors;const propertyNames=Object.getOwnPropertyNames(source);for(let i=0;i<propertyNames.length;i++){let p=propertyNames[i];if(p in excludeProps){continue}if(noAccessors){target[p]=source[p]}else{let pd=Object.getOwnPropertyDescriptor(source,p);if(pd){pd.configurable=true;Object.defineProperty(target,p,pd)}}}}function mixinBehaviors(behaviors,klass){return GenerateClassFromInfo({},LegacyElementMixin(klass),behaviors)}function applyBehaviors(proto,behaviors,lifecycle){for(let i=0;i<behaviors.length;i++){applyInfo(proto,behaviors[i],lifecycle,excludeOnBehaviors)}}function applyInfo(proto,info,lifecycle,excludeProps){copyProperties(info,proto,excludeProps);for(let p in lifecycleProps){if(info[p]){lifecycle[p]=lifecycle[p]||[];lifecycle[p].push(info[p])}}}function flattenBehaviors(behaviors,list,exclude){list=list||[];for(let i=behaviors.length-1;i>=0;i--){let b=behaviors[i];if(b){if(Array.isArray(b)){flattenBehaviors(b,list)}else{if(list.indexOf(b)<0&&(!exclude||exclude.indexOf(b)<0)){list.unshift(b)}}}else{console.warn("behavior is null, check for missing or 404 import")}}return list}function mergeProperties(target,source){for(const p in source){const targetInfo=target[p];const sourceInfo=source[p];if(!("value"in sourceInfo)&&targetInfo&&"value"in targetInfo){target[p]=Object.assign({value:targetInfo.value},sourceInfo)}else{target[p]=sourceInfo}}}function GenerateClassFromInfo(info,Base,behaviors){let behaviorList;const lifecycle={};class PolymerGenerated extends Base{static _finalizeClass(){if(!this.hasOwnProperty(JSCompiler_renameProperty("generatedFrom",this))){super._finalizeClass()}else{if(behaviorList){for(let i=0,b;i<behaviorList.length;i++){b=behaviorList[i];if(b.properties){this.createProperties(b.properties)}if(b.observers){this.createObservers(b.observers,b.properties)}}}if(info.properties){this.createProperties(info.properties)}if(info.observers){this.createObservers(info.observers,info.properties)}this._prepareTemplate()}}static get properties(){const properties={};if(behaviorList){for(let i=0;i<behaviorList.length;i++){mergeProperties(properties,behaviorList[i].properties)}}mergeProperties(properties,info.properties);return properties}static get observers(){let observers=[];if(behaviorList){for(let i=0,b;i<behaviorList.length;i++){b=behaviorList[i];if(b.observers){observers=observers.concat(b.observers)}}}if(info.observers){observers=observers.concat(info.observers)}return observers}created(){super.created();const list=lifecycle.created;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}_registered(){const generatedProto=PolymerGenerated.prototype;if(!generatedProto.hasOwnProperty("__hasRegisterFinished")){generatedProto.__hasRegisterFinished=true;super._registered();const proto=Object.getPrototypeOf(this);let list=lifecycle.beforeRegister;if(list){for(let i=0;i<list.length;i++){list[i].call(proto)}}list=lifecycle.registered;if(list){for(let i=0;i<list.length;i++){list[i].call(proto)}}}}_applyListeners(){super._applyListeners();const list=lifecycle.listeners;if(list){for(let i=0;i<list.length;i++){const listeners=list[i];if(listeners){for(let l in listeners){this._addMethodEventListenerToNode(this,l,listeners[l])}}}}}_ensureAttributes(){const list=lifecycle.hostAttributes;if(list){for(let i=list.length-1;i>=0;i--){const hostAttributes=list[i];for(let a in hostAttributes){this._ensureAttribute(a,hostAttributes[a])}}}super._ensureAttributes()}ready(){super.ready();let list=lifecycle.ready;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}attached(){super.attached();let list=lifecycle.attached;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}detached(){super.detached();let list=lifecycle.detached;if(list){for(let i=0;i<list.length;i++){list[i].call(this)}}}attributeChanged(name,old,value){super.attributeChanged();let list=lifecycle.attributeChanged;if(list){for(let i=0;i<list.length;i++){list[i].call(this,name,old,value)}}}}if(behaviors){if(!Array.isArray(behaviors)){behaviors=[behaviors]}let superBehaviors=Base.prototype.behaviors;behaviorList=flattenBehaviors(behaviors,null,superBehaviors);PolymerGenerated.prototype.behaviors=superBehaviors?superBehaviors.concat(behaviors):behaviorList}const copyPropertiesToProto=proto=>{if(behaviorList){applyBehaviors(proto,behaviorList,lifecycle)}applyInfo(proto,info,lifecycle,excludeOnInfo)};{copyPropertiesToProto(PolymerGenerated.prototype)}PolymerGenerated.generatedFrom=info;return PolymerGenerated}const Class=function(info,mixin){if(!info){console.warn("Polymer.Class requires `info` argument")}let klass=mixin?mixin(LegacyElementMixin(HTMLElement)):LegacyElementMixin(HTMLElement);klass=GenerateClassFromInfo(info,klass,info.behaviors);klass.is=klass.prototype.is=info.is;return klass};let mutablePropertyChange;(()=>{mutablePropertyChange=MutableData._mutablePropertyChange})();const OptionalMutableDataBehavior={properties:{mutableData:Boolean},_shouldPropertyChange(property,value,old){return mutablePropertyChange(this,property,value,old,this.mutableData)}};const Polymer=function(info){let klass;if(typeof info==="function"){klass=info}else{klass=Polymer.Class(info)}customElements.define(klass.is,klass);return klass};Polymer.Class=Class;const Templatizer={templatize(template,mutableData){this._templatizerTemplate=template;this.ctor=templatize(template,this,{mutableData:Boolean(mutableData),parentModel:this._parentModel,instanceProps:this._instanceProps,forwardHostProp:this._forwardHostPropV2,notifyInstanceProp:this._notifyInstancePropV2})},stamp(model){return new this.ctor(model)},modelForElement(el){return modelForElement(this._templatizerTemplate,el)}};const domBindBase=GestureEventListeners(OptionalMutableData(PropertyEffects(HTMLElement)));class DomBind extends domBindBase{static get observedAttributes(){return["mutable-data"]}constructor(){super();this.root=null;this.$=null;this.__children=null}attributeChangedCallback(){this.mutableData=true}connectedCallback(){this.style.display="none";this.render()}disconnectedCallback(){this.__removeChildren()}__insertChildren(){wrap(wrap(this).parentNode).insertBefore(this.root,this)}__removeChildren(){if(this.__children){for(let i=0;i<this.__children.length;i++){this.root.appendChild(this.__children[i])}}}render(){let template;if(!this.__children){template=template||this.querySelector("template");if(!template){let observer=new MutationObserver((()=>{template=this.querySelector("template");if(template){observer.disconnect();this.render()}else{throw new Error("dom-bind requires a <template> child")}}));observer.observe(this,{childList:true});return}this.root=this._stampTemplate(template);this.$=this.root.$;this.__children=[];for(let n=this.root.firstChild;n;n=n.nextSibling){this.__children[this.__children.length]=n}this._enableProperties()}this.__insertChildren();this.dispatchEvent(new CustomEvent("dom-change",{bubbles:true,composed:true}))}}customElements.define("dom-bind",DomBind);let ArraySelectorMixin=dedupingMixin((superClass=>{let elementBase=ElementMixin(superClass);class ArraySelectorMixin extends elementBase{static get properties(){return{items:{type:Array},multi:{type:Boolean,value:false},selected:{type:Object,notify:true},selectedItem:{type:Object,notify:true},toggle:{type:Boolean,value:false}}}static get observers(){return["__updateSelection(multi, items.*)"]}constructor(){super();this.__lastItems=null;this.__lastMulti=null;this.__selectedMap=null}__updateSelection(multi,itemsInfo){let path=itemsInfo.path;if(path==JSCompiler_renameProperty("items",this)){let newItems=itemsInfo.base||[];let lastItems=this.__lastItems;let lastMulti=this.__lastMulti;if(multi!==lastMulti){this.clearSelection()}if(lastItems){let splices=calculateSplices(newItems,lastItems);this.__applySplices(splices)}this.__lastItems=newItems;this.__lastMulti=multi}else if(itemsInfo.path==`${JSCompiler_renameProperty("items",this)}.splices`){this.__applySplices(itemsInfo.value.indexSplices)}else{let part=path.slice(`${JSCompiler_renameProperty("items",this)}.`.length);let idx=parseInt(part,10);if(part.indexOf(".")<0&&part==idx){this.__deselectChangedIdx(idx)}}}__applySplices(splices){let selected=this.__selectedMap;for(let i=0;i<splices.length;i++){let s=splices[i];selected.forEach(((idx,item)=>{if(idx<s.index);else if(idx>=s.index+s.removed.length){selected.set(item,idx+s.addedCount-s.removed.length)}else{selected.set(item,-1)}}));for(let j=0;j<s.addedCount;j++){let idx=s.index+j;if(selected.has(this.items[idx])){selected.set(this.items[idx],idx)}}}this.__updateLinks();let sidx=0;selected.forEach(((idx,item)=>{if(idx<0){if(this.multi){this.splice(JSCompiler_renameProperty("selected",this),sidx,1)}else{this.selected=this.selectedItem=null}selected.delete(item)}else{sidx++}}))}__updateLinks(){this.__dataLinkedPaths={};if(this.multi){let sidx=0;this.__selectedMap.forEach((idx=>{if(idx>=0){this.linkPaths(`${JSCompiler_renameProperty("items",this)}.${idx}`,`${JSCompiler_renameProperty("selected",this)}.${sidx++}`)}}))}else{this.__selectedMap.forEach((idx=>{this.linkPaths(JSCompiler_renameProperty("selected",this),`${JSCompiler_renameProperty("items",this)}.${idx}`);this.linkPaths(JSCompiler_renameProperty("selectedItem",this),`${JSCompiler_renameProperty("items",this)}.${idx}`)}))}}clearSelection(){this.__dataLinkedPaths={};this.__selectedMap=new Map;this.selected=this.multi?[]:null;this.selectedItem=null}isSelected(item){return this.__selectedMap.has(item)}isIndexSelected(idx){return this.isSelected(this.items[idx])}__deselectChangedIdx(idx){let sidx=this.__selectedIndexForItemIndex(idx);if(sidx>=0){let i=0;this.__selectedMap.forEach(((idx,item)=>{if(sidx==i++){this.deselect(item)}}))}}__selectedIndexForItemIndex(idx){let selected=this.__dataLinkedPaths[`${JSCompiler_renameProperty("items",this)}.${idx}`];if(selected){return parseInt(selected.slice(`${JSCompiler_renameProperty("selected",this)}.`.length),10)}}deselect(item){let idx=this.__selectedMap.get(item);if(idx>=0){this.__selectedMap.delete(item);let sidx;if(this.multi){sidx=this.__selectedIndexForItemIndex(idx)}this.__updateLinks();if(this.multi){this.splice(JSCompiler_renameProperty("selected",this),sidx,1)}else{this.selected=this.selectedItem=null}}}deselectIndex(idx){this.deselect(this.items[idx])}select(item){this.selectIndex(this.items.indexOf(item))}selectIndex(idx){let item=this.items[idx];if(!this.isSelected(item)){if(!this.multi){this.__selectedMap.clear()}this.__selectedMap.set(item,idx);this.__updateLinks();if(this.multi){this.push(JSCompiler_renameProperty("selected",this),item)}else{this.selected=this.selectedItem=item}}else if(this.toggle){this.deselectIndex(idx)}}}return ArraySelectorMixin}));let baseArraySelector=ArraySelectorMixin(PolymerElement);class ArraySelector extends baseArraySelector{static get is(){return"array-selector"}static get template(){return null}}customElements.define(ArraySelector.is,ArraySelector);const customStyleInterface=new CustomStyleInterface$1;if(!window.ShadyCSS){window.ShadyCSS={prepareTemplate(template,elementName,elementExtends){},prepareTemplateDom(template,elementName){},prepareTemplateStyles(template,elementName,elementExtends){},styleSubtree(element,properties){customStyleInterface.processStyles();updateNativeProperties(element,properties)},styleElement(element){customStyleInterface.processStyles()},styleDocument(properties){customStyleInterface.processStyles();updateNativeProperties(document.body,properties)},getComputedStyleValue(element,property){return getComputedStyleValue(element,property)},flushCustomStyles(){},nativeCss:nativeCssVariables,nativeShadow:nativeShadow,cssBuild:cssBuild,disableRuntime:disableRuntime}}window.ShadyCSS.CustomStyleInterface=customStyleInterface;const attr="include";const CustomStyleInterface=window.ShadyCSS.CustomStyleInterface;class CustomStyle extends HTMLElement{constructor(){super();this._style=null;CustomStyleInterface.addCustomStyle(this)}getStyle(){if(this._style){return this._style}const style=this.querySelector("style");if(!style){return null}this._style=style;const include=style.getAttribute(attr);if(include){style.removeAttribute(attr);style.textContent=cssFromModules(include)+style.textContent}if(this.ownerDocument!==window.document){window.document.head.appendChild(this)}return this._style}}window.customElements.define("custom-style",CustomStyle);const Base=LegacyElementMixin(HTMLElement).prototype;export{Base,Debouncer,DomIf,DomRepeat,FlattenedNodesObserver,OptionalMutableDataBehavior,Polymer,PolymerElement,TemplateInstanceBase,Templatizer,afterNextRender,animationFrame,beforeNextRender,calculateSplices,dashToCamelCase,dedupingMixin,dom,enqueueDebouncer,flush,gestures$1 as gestures,get,html,idlePeriod,matches,microTask,mixinBehaviors,templatize,timeOut,translate,useShadow};
\ No newline at end of file
+window.JSCompiler_renameProperty=function(t,e){return t};let t=0,e=0,s=[],n=0,r=document.createTextNode("");new window.MutationObserver((function(){const t=s.length;for(let e=0;e<t;e++){let t=s[e];if(t)try{t()}catch(t){setTimeout((()=>{throw t}))}}s.splice(0,t),e+=t})).observe(r,{characterData:!0});const i={after:t=>({run:e=>window.setTimeout(e,t),cancel(t){window.clearTimeout(t)}}),run:(t,e)=>window.setTimeout(t,e),cancel(t){window.clearTimeout(t)}},o={run:t=>window.requestAnimationFrame(t),cancel(t){window.cancelAnimationFrame(t)}},a={run:t=>window.requestIdleCallback?window.requestIdleCallback(t):window.setTimeout(t,16),cancel(t){window.cancelIdleCallback?window.cancelIdleCallback(t):window.clearTimeout(t)}},l={run:e=>(r.textContent=n++,s.push(e),t++),cancel(t){const n=t-e;if(n>=0){if(!s[n])throw new Error("invalid async handle: "+t);s[n]=null}}};let h=0;const d=function(t){let e=t.__mixinApplications;e||(e=new WeakMap,t.__mixinApplications=e);let s=h++;return function(n){let r=n.__mixinSet;if(r&&r[s])return n;let i=e,o=i.get(n);o||(o=t(n),i.set(n,o));let a=Object.create(o.__mixinSet||r||null);return a[s]=!0,o.__mixinSet=a,o}};class c{constructor(){this._asyncModule=null,this._callback=null,this._timer=null}setConfig(t,e){this._asyncModule=t,this._callback=e,this._timer=this._asyncModule.run((()=>{this._timer=null,u.delete(this),this._callback()}))}cancel(){this.isActive()&&(this._cancelAsync(),u.delete(this))}_cancelAsync(){this.isActive()&&(this._asyncModule.cancel(this._timer),this._timer=null)}flush(){this.isActive()&&(this.cancel(),this._callback())}isActive(){return null!=this._timer}static debounce(t,e,s){return t instanceof c?t._cancelAsync():t=new c,t.setConfig(e,s),t}}let u=new Set;const p=function(t){u.add(t)},_=function(){const t=Boolean(u.size);return u.forEach((t=>{try{t.flush()}catch(t){setTimeout((()=>{throw t}))}})),t};let f,m,y=/(url\()([^)]*)(\))/g,g=/(^\/)|(^#)|(^[\w-\d]*:)/;function b(t,e){if(t&&g.test(t))return t;if(void 0===f){f=!1;try{const t=new URL("b","http://a");t.pathname="c%20d",f="http://a/c%20d"===t.href}catch(t){}}return e||(e=document.baseURI||window.location.href),f?new URL(t,e).href:(m||(m=document.implementation.createHTMLDocument("temp"),m.base=m.createElement("base"),m.head.appendChild(m.base),m.anchor=m.createElement("a"),m.body.appendChild(m.anchor)),m.base.href=e,m.anchor.href=t,m.anchor.href||t)}function P(t,e){return t.replace(y,(function(t,s,n,r){return s+"'"+b(n.replace(/["']/g,""),e)+"'"+r}))}function C(t){return t.substring(0,t.lastIndexOf("/")+1)}const v=!window.ShadyDOM;Boolean(!window.ShadyCSS||window.ShadyCSS.nativeCss);let S=C(document.baseURI||window.location.href),w=window.Polymer&&window.Polymer.sanitizeDOMValue||void 0;const E=window.ShadyDOM&&window.ShadyDOM.noPatch&&window.ShadyDOM.wrap?window.ShadyDOM.wrap:t=>t;let T="string"==typeof document.head.style.touchAction,O="__polymerGestures",N="__polymerGesturesHandled",x="__polymerGesturesTouchAction",A=["mousedown","mousemove","mouseup","click"],I=[0,1,4,2],M=function(){try{return 1===new MouseEvent("test",{buttons:1}).buttons}catch(t){return!1}}();function R(t){return A.indexOf(t)>-1}let L=!1;function k(t){R(t)}!function(){try{let t=Object.defineProperty({},"passive",{get(){L=!0}});window.addEventListener("test",null,t),window.removeEventListener("test",null,t)}catch(t){}}();let D=navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);const F=[],H={button:!0,input:!0,keygen:!0,meter:!0,output:!0,textarea:!0,progress:!0,select:!0},z={button:!0,command:!0,fieldset:!0,input:!0,keygen:!0,optgroup:!0,option:!0,select:!0,textarea:!0};function j(t){let e=Array.prototype.slice.call(t.labels||[]);if(!e.length){e=[];let s=t.getRootNode();if(t.id){let n=s.querySelectorAll(`label[for = ${t.id}]`);for(let t=0;t<n.length;t++)e.push(n[t])}}return e}let B=function(t){let e=t.sourceCapabilities;var s;if((!e||e.firesTouchEvents)&&(t[N]={skip:!0},"click"===t.type)){let e=!1,n=U(t);for(let t=0;t<n.length;t++){if(n[t].nodeType===Node.ELEMENT_NODE)if("label"===n[t].localName)F.push(n[t]);else if(s=n[t],H[s.localName]){let s=j(n[t]);for(let t=0;t<s.length;t++)e=e||F.indexOf(s[t])>-1}if(n[t]===Y.mouse.target)return}if(e)return;t.preventDefault(),t.stopPropagation()}};function q(t){let e=D?["click"]:A;for(let s,n=0;n<e.length;n++)s=e[n],t?(F.length=0,document.addEventListener(s,B,!0)):document.removeEventListener(s,B,!0)}function $(t){let e=t.type;if(!R(e))return!1;if("mousemove"===e){let e=void 0===t.buttons?1:t.buttons;return t instanceof window.MouseEvent&&!M&&(e=I[t.which]||0),Boolean(1&e)}return 0===(void 0===t.button?0:t.button)}let Y={mouse:{target:null,mouseIgnoreJob:null},touch:{x:0,y:0,id:-1,scrollDecided:!1}};function J(t,e,s){t.movefn=e,t.upfn=s,document.addEventListener("mousemove",e),document.addEventListener("mouseup",s)}function V(t){document.removeEventListener("mousemove",t.movefn),document.removeEventListener("mouseup",t.upfn),t.movefn=null,t.upfn=null}document.addEventListener("touchend",(function(t){Y.mouse.mouseIgnoreJob||q(!0),Y.mouse.target=U(t)[0],Y.mouse.mouseIgnoreJob=c.debounce(Y.mouse.mouseIgnoreJob,i.after(2500),(function(){q(),Y.mouse.target=null,Y.mouse.mouseIgnoreJob=null}))}),!!L&&{passive:!0});const U=window.ShadyDOM&&window.ShadyDOM.noPatch?window.ShadyDOM.composedPath:t=>t.composedPath&&t.composedPath()||[],X={},W=[];function G(t,e){let s=document.elementFromPoint(t,e),n=s;for(;n&&n.shadowRoot&&!window.ShadyDOM;){let r=n;if(n=n.shadowRoot.elementFromPoint(t,e),r===n)break;n&&(s=n)}return s}function Z(t){const e=U(t);return e.length>0?e[0]:t.target}function K(t){let e,s=t.type,n=t.currentTarget.__polymerGestures;if(!n)return;let r=n[s];if(r){if(!t[N]&&(t[N]={},"touch"===s.slice(0,5))){let e=(t=t).changedTouches[0];if("touchstart"===s&&1===t.touches.length&&(Y.touch.id=e.identifier),Y.touch.id!==e.identifier)return;T||"touchstart"!==s&&"touchmove"!==s||function(t){let e=t.changedTouches[0],s=t.type;if("touchstart"===s)Y.touch.x=e.clientX,Y.touch.y=e.clientY,Y.touch.scrollDecided=!1;else if("touchmove"===s){if(Y.touch.scrollDecided)return;Y.touch.scrollDecided=!0;let s=function(t){let e="auto",s=U(t);for(let t,n=0;n<s.length;n++)if(t=s[n],t[x]){e=t[x];break}return e}(t),n=!1,r=Math.abs(Y.touch.x-e.clientX),i=Math.abs(Y.touch.y-e.clientY);t.cancelable&&("none"===s?n=!0:"pan-x"===s?n=i>r:"pan-y"===s&&(n=r>i)),n?t.preventDefault():rt("track")}}(t)}if(e=t[N],!e.skip){for(let s,n=0;n<W.length;n++)s=W[n],r[s.name]&&!e[s.name]&&s.flow&&s.flow.start.indexOf(t.type)>-1&&s.reset&&s.reset();for(let n,i=0;i<W.length;i++)n=W[i],r[n.name]&&!e[n.name]&&(e[n.name]=!0,n[s](t))}}}function Q(t,e,s){return!!X[e]&&(function(t,e,s){let n=X[e],r=n.deps,i=n.name,o=t[O];o||(t[O]=o={});for(let e,s,n=0;n<r.length;n++)e=r[n],D&&R(e)&&"click"!==e||(s=o[e],s||(o[e]=s={_count:0}),0===s._count&&t.addEventListener(e,K,k(e)),s[i]=(s[i]||0)+1,s._count=(s._count||0)+1);t.addEventListener(e,s),n.touchAction&&st(t,n.touchAction)}(t,e,s),!0)}function tt(t,e,s){return!!X[e]&&(function(t,e,s){let n=X[e],r=n.deps,i=n.name,o=t[O];if(o)for(let e,s,n=0;n<r.length;n++)e=r[n],s=o[e],s&&s[i]&&(s[i]=(s[i]||1)-1,s._count=(s._count||1)-1,0===s._count&&t.removeEventListener(e,K,k(e)));t.removeEventListener(e,s)}(t,e,s),!0)}function et(t){W.push(t);for(let e=0;e<t.emits.length;e++)X[t.emits[e]]=t}function st(t,e){T&&t instanceof HTMLElement&&l.run((()=>{t.style.touchAction=e})),t[x]=e}function nt(t,e,s){let n=new Event(e,{bubbles:!0,cancelable:!0,composed:!0});if(n.detail=s,E(t).dispatchEvent(n),n.defaultPrevented){let t=s.preventer||s.sourceEvent;t&&t.preventDefault&&t.preventDefault()}}function rt(t){let e=function(t){for(let e,s=0;s<W.length;s++){e=W[s];for(let s,n=0;n<e.emits.length;n++)if(s=e.emits[n],s===t)return e}return null}(t);e.info&&(e.info.prevent=!0)}function it(t,e,s,n){e&&nt(e,t,{x:s.clientX,y:s.clientY,sourceEvent:s,preventer:n,prevent:function(t){return rt(t)}})}function ot(t,e,s){if(t.prevent)return!1;if(t.started)return!0;let n=Math.abs(t.x-e),r=Math.abs(t.y-s);return n>=5||r>=5}function at(t,e,s){if(!e)return;let n,r=t.moves[t.moves.length-2],i=t.moves[t.moves.length-1],o=i.x-t.x,a=i.y-t.y,l=0;r&&(n=i.x-r.x,l=i.y-r.y),nt(e,"track",{state:t.state,x:s.clientX,y:s.clientY,dx:o,dy:a,ddx:n,ddy:l,sourceEvent:s,hover:function(){return G(s.clientX,s.clientY)}})}function lt(t,e,s){let n=Math.abs(e.clientX-t.x),r=Math.abs(e.clientY-t.y),i=Z(s||e);!i||z[i.localName]&&i.hasAttribute("disabled")||(isNaN(n)||isNaN(r)||n<=25&&r<=25||function(t){if("click"===t.type){if(0===t.detail)return!0;let e=Z(t);if(!e.nodeType||e.nodeType!==Node.ELEMENT_NODE)return!0;let s=e.getBoundingClientRect(),n=t.pageX,r=t.pageY;return!(n>=s.left&&n<=s.right&&r>=s.top&&r<=s.bottom)}return!1}(e))&&(t.prevent||nt(i,"tap",{x:e.clientX,y:e.clientY,sourceEvent:e,preventer:s}))}et({name:"downup",deps:["mousedown","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["down","up"],info:{movefn:null,upfn:null},reset:function(){V(this.info)},mousedown:function(t){if(!$(t))return;let e=Z(t),s=this;J(this.info,(function(t){$(t)||(it("up",e,t),V(s.info))}),(function(t){$(t)&&it("up",e,t),V(s.info)})),it("down",e,t)},touchstart:function(t){it("down",Z(t),t.changedTouches[0],t)},touchend:function(t){it("up",Z(t),t.changedTouches[0],t)}}),et({name:"track",touchAction:"none",deps:["mousedown","touchstart","touchmove","touchend"],flow:{start:["mousedown","touchstart"],end:["mouseup","touchend"]},emits:["track"],info:{x:0,y:0,state:"start",started:!1,moves:[],addMove:function(t){this.moves.length>2&&this.moves.shift(),this.moves.push(t)},movefn:null,upfn:null,prevent:!1},reset:function(){this.info.state="start",this.info.started=!1,this.info.moves=[],this.info.x=0,this.info.y=0,this.info.prevent=!1,V(this.info)},mousedown:function(t){if(!$(t))return;let e=Z(t),s=this,n=function(t){let n=t.clientX,r=t.clientY;ot(s.info,n,r)&&(s.info.state=s.info.started?"mouseup"===t.type?"end":"track":"start","start"===s.info.state&&rt("tap"),s.info.addMove({x:n,y:r}),$(t)||(s.info.state="end",V(s.info)),e&&at(s.info,e,t),s.info.started=!0)};J(this.info,n,(function(t){s.info.started&&n(t),V(s.info)})),this.info.x=t.clientX,this.info.y=t.clientY},touchstart:function(t){let e=t.changedTouches[0];this.info.x=e.clientX,this.info.y=e.clientY},touchmove:function(t){let e=Z(t),s=t.changedTouches[0],n=s.clientX,r=s.clientY;ot(this.info,n,r)&&("start"===this.info.state&&rt("tap"),this.info.addMove({x:n,y:r}),at(this.info,e,s),this.info.state="track",this.info.started=!0)},touchend:function(t){let e=Z(t),s=t.changedTouches[0];this.info.started&&(this.info.state="end",this.info.addMove({x:s.clientX,y:s.clientY}),at(this.info,e,s))}}),et({name:"tap",deps:["mousedown","click","touchstart","touchend"],flow:{start:["mousedown","touchstart"],end:["click","touchend"]},emits:["tap"],info:{x:NaN,y:NaN,prevent:!1},reset:function(){this.info.x=NaN,this.info.y=NaN,this.info.prevent=!1},mousedown:function(t){$(t)&&(this.info.x=t.clientX,this.info.y=t.clientY)},click:function(t){$(t)&&lt(this.info,t)},touchstart:function(t){const e=t.changedTouches[0];this.info.x=e.clientX,this.info.y=e.clientY},touchend:function(t){lt(this.info,t.changedTouches[0],t)}});const ht=Z,dt=Q,ct=tt;var ut=Object.freeze({__proto__:null,gestures:X,recognizers:W,deepTargetFind:G,addListener:Q,removeListener:tt,register:et,setTouchAction:st,prevent:rt,resetMouseCanceller:function(){Y.mouse.mouseIgnoreJob&&Y.mouse.mouseIgnoreJob.flush()},findOriginalTarget:ht,add:dt,remove:ct});let pt={},_t={};class ft extends HTMLElement{static get observedAttributes(){return["id"]}static import(t,e){if(t){let s=function(t){return pt[t]||_t[t.toLowerCase()]}(t);return s&&e?s.querySelector(e):s}return null}attributeChangedCallback(t,e,s,n){e!==s&&this.register()}get assetpath(){if(!this.__assetpath){const t=window.HTMLImports&&HTMLImports.importForElement?HTMLImports.importForElement(this)||document:this.ownerDocument,e=b(this.getAttribute("assetpath")||"",t.baseURI);this.__assetpath=C(e)}return this.__assetpath}register(t){var e;(t=t||this.id)&&(this.id=t,function(t,e){pt[t]=_t[t.toLowerCase()]=e}(t,this),(e=this).querySelector("style")&&console.warn("dom-module %s has style outside template",e.id))}}ft.prototype.modules=pt,customElements.define("dom-module",ft);function mt(t){return ft.import(t)}function yt(t){const e=P((t.body?t.body:t).textContent,t.baseURI),s=document.createElement("style");return s.textContent=e,s}function gt(t){const e=t.trim().split(/\s+/),s=[];for(let t=0;t<e.length;t++)s.push(...bt(e[t]));return s}function bt(t){const e=mt(t);if(!e)return console.warn("Could not find style data in module named",t),[];if(void 0===e._styles){const t=[];t.push(...Ct(e));const s=e.querySelector("template");s&&t.push(...Pt(s,e.assetpath)),e._styles=t}return e._styles}function Pt(t,e){if(!t._styles){const s=[],n=t.content.querySelectorAll("style");for(let t=0;t<n.length;t++){let r=n[t],i=r.getAttribute("include");i&&s.push(...gt(i).filter((function(t,e,s){return s.indexOf(t)===e}))),e&&(r.textContent=P(r.textContent,e)),s.push(r)}t._styles=s}return t._styles}function Ct(t){const e=[],s=t.querySelectorAll("link[rel=import][type~=css]");for(let t=0;t<s.length;t++){let n=s[t];if(n.import){const t=n.import,s=n.hasAttribute("shady-unscoped");if(s&&!t._unscopedStyle){const e=yt(t);e.setAttribute("shady-unscoped",""),t._unscopedStyle=e}else t._style||(t._style=yt(t));e.push(s?t._unscopedStyle:t._style)}}return e}function vt(t){let e=mt(t);if(e&&void 0===e._cssText){let t=function(t){let e="",s=Ct(t);for(let t=0;t<s.length;t++)e+=s[t].textContent;return e}(e),s=e.querySelector("template");s&&(t+=function(t,e){let s="";const n=Pt(t,e);for(let t=0;t<n.length;t++){let e=n[t];e.parentNode&&e.parentNode.removeChild(e),s+=e.textContent}return s}(s,e.assetpath)),e._cssText=t||null}return e||console.warn("Could not find style data in module named",t),e&&e._cssText||""}function St(t){return t.indexOf(".")>=0}function wt(t){let e=t.indexOf(".");return-1===e?t:t.slice(0,e)}function Et(t,e){return 0===t.indexOf(e+".")}function Tt(t,e){return 0===e.indexOf(t+".")}function Ot(t,e,s){return e+s.slice(t.length)}function Nt(t,e){return t===e||Et(t,e)||Tt(t,e)}function xt(t){if(Array.isArray(t)){let e=[];for(let s=0;s<t.length;s++){let n=t[s].toString().split(".");for(let t=0;t<n.length;t++)e.push(n[t])}return e.join(".")}return t}function At(t){return Array.isArray(t)?xt(t).split("."):t.toString().split(".")}function It(t,e,s){let n=t,r=At(e);for(let t=0;t<r.length;t++){if(!n)return;n=n[r[t]]}return s&&(s.path=r.join(".")),n}function Mt(t,e,s){let n=t,r=At(e),i=r[r.length-1];if(r.length>1){for(let t=0;t<r.length-1;t++){if(n=n[r[t]],!n)return}n[i]=s}else n[e]=s;return r.join(".")}const Rt={},Lt=/-[a-z]/g,kt=/([A-Z])/g;function Dt(t){return Rt[t]||(Rt[t]=t.indexOf("-")<0?t:t.replace(Lt,(t=>t[1].toUpperCase())))}function Ft(t){return Rt[t]||(Rt[t]=t.replace(kt,"-$1").toLowerCase())}const Ht=l,zt=d((t=>class extends t{static createProperties(t){const e=this.prototype;for(let s in t)s in e||e._createPropertyAccessor(s)}static attributeNameForProperty(t){return t.toLowerCase()}static typeForProperty(t){}_createPropertyAccessor(t,e){this._addPropertyToAttributeMap(t),this.hasOwnProperty("__dataHasAccessor")||(this.__dataHasAccessor=Object.assign({},this.__dataHasAccessor)),this.__dataHasAccessor[t]||(this.__dataHasAccessor[t]=!0,this._definePropertyAccessor(t,e))}_addPropertyToAttributeMap(t){if(this.hasOwnProperty("__dataAttributes")||(this.__dataAttributes=Object.assign({},this.__dataAttributes)),!this.__dataAttributes[t]){const e=this.constructor.attributeNameForProperty(t);this.__dataAttributes[e]=t}}_definePropertyAccessor(t,e){Object.defineProperty(this,t,{get(){return this._getProperty(t)},set:e?function(){}:function(e){this._setProperty(t,e)}})}constructor(){super(),this.__dataEnabled=!1,this.__dataReady=!1,this.__dataInvalid=!1,this.__data={},this.__dataPending=null,this.__dataOld=null,this.__dataInstanceProps=null,this.__serializing=!1,this._initializeProperties()}ready(){this.__dataReady=!0,this._flushProperties()}_initializeProperties(){for(let t in this.__dataHasAccessor)this.hasOwnProperty(t)&&(this.__dataInstanceProps=this.__dataInstanceProps||{},this.__dataInstanceProps[t]=this[t],delete this[t])}_initializeInstanceProperties(t){Object.assign(this,t)}_setProperty(t,e){this._setPendingProperty(t,e)&&this._invalidateProperties()}_getProperty(t){return this.__data[t]}_setPendingProperty(t,e,s){let n=this.__data[t],r=this._shouldPropertyChange(t,e,n);return r&&(this.__dataPending||(this.__dataPending={},this.__dataOld={}),this.__dataOld&&!(t in this.__dataOld)&&(this.__dataOld[t]=n),this.__data[t]=e,this.__dataPending[t]=e),r}_invalidateProperties(){!this.__dataInvalid&&this.__dataReady&&(this.__dataInvalid=!0,Ht.run((()=>{this.__dataInvalid&&(this.__dataInvalid=!1,this._flushProperties())})))}_enableProperties(){this.__dataEnabled||(this.__dataEnabled=!0,this.__dataInstanceProps&&(this._initializeInstanceProperties(this.__dataInstanceProps),this.__dataInstanceProps=null),this.ready())}_flushProperties(){const t=this.__data,e=this.__dataPending,s=this.__dataOld;this._shouldPropertiesChange(t,e,s)&&(this.__dataPending=null,this.__dataOld=null,this._propertiesChanged(t,e,s))}_shouldPropertiesChange(t,e,s){return Boolean(e)}_propertiesChanged(t,e,s){}_shouldPropertyChange(t,e,s){return s!==e&&(s==s||e==e)}attributeChangedCallback(t,e,s,n){e!==s&&this._attributeToProperty(t,s),super.attributeChangedCallback&&super.attributeChangedCallback(t,e,s,n)}_attributeToProperty(t,e,s){if(!this.__serializing){const n=this.__dataAttributes,r=n&&n[t]||t;this[r]=this._deserializeValue(e,s||this.constructor.typeForProperty(r))}}_propertyToAttribute(t,e,s){this.__serializing=!0,s=arguments.length<3?this[t]:s,this._valueToNodeAttribute(this,s,e||this.constructor.attributeNameForProperty(t)),this.__serializing=!1}_valueToNodeAttribute(t,e,s){const n=this._serializeValue(e);void 0===n?t.removeAttribute(s):("class"!==s&&"name"!==s&&"slot"!==s||(t=E(t)),t.setAttribute(s,n))}_serializeValue(t){switch(typeof t){case"boolean":return t?"":void 0;default:return null!=t?t.toString():void 0}}_deserializeValue(t,e){switch(e){case Boolean:return null!==t;case Number:return Number(t);default:return t}}})),jt={};let Bt=HTMLElement.prototype;for(;Bt;){let t=Object.getOwnPropertyNames(Bt);for(let e=0;e<t.length;e++)jt[t[e]]=!0;Bt=Object.getPrototypeOf(Bt)}const qt=d((t=>{const e=zt(t);return class extends e{static createPropertiesForAttributes(){let t=this.observedAttributes;for(let e=0;e<t.length;e++)this.prototype._createPropertyAccessor(Dt(t[e]))}static attributeNameForProperty(t){return Ft(t)}_initializeProperties(){this.__dataProto&&(this._initializeProtoProperties(this.__dataProto),this.__dataProto=null),super._initializeProperties()}_initializeProtoProperties(t){for(let e in t)this._setProperty(e,t[e])}_ensureAttribute(t,e){const s=this;s.hasAttribute(t)||this._valueToNodeAttribute(s,e,t)}_serializeValue(t){switch(typeof t){case"object":if(t instanceof Date)return t.toString();if(t)try{return JSON.stringify(t)}catch(t){return""}default:return super._serializeValue(t)}}_deserializeValue(t,e){let s;switch(e){case Object:try{s=JSON.parse(t)}catch(e){s=t}break;case Array:try{s=JSON.parse(t)}catch(e){s=null,console.warn("Polymer::Attributes: couldn't decode Array as JSON: "+t)}break;case Date:s=isNaN(t)?String(t):Number(t),s=new Date(s);break;default:s=super._deserializeValue(t,e)}return s}_definePropertyAccessor(t,e){!function(t,e){if(!jt[e]){let s=t[e];void 0!==s&&(t.__data?t._setPendingProperty(e,s):(t.__dataProto?t.hasOwnProperty(JSCompiler_renameProperty("__dataProto",t))||(t.__dataProto=Object.create(t.__dataProto)):t.__dataProto={},t.__dataProto[e]=s))}}(this,t),super._definePropertyAccessor(t,e)}_hasAccessor(t){return this.__dataHasAccessor&&this.__dataHasAccessor[t]}_isPropertyPending(t){return Boolean(this.__dataPending&&t in this.__dataPending)}}})),$t=document.createTreeWalker(document,NodeFilter.SHOW_ALL,null,!1),Yt={"dom-if":!0,"dom-repeat":!0};function Jt(t){let e=t.getAttribute("is");if(e&&Yt[e]){let s=t;for(s.removeAttribute("is"),t=s.ownerDocument.createElement(e),s.parentNode.replaceChild(t,s),t.appendChild(s);s.attributes.length;)t.setAttribute(s.attributes[0].name,s.attributes[0].value),s.removeAttribute(s.attributes[0].name)}return t}function Vt(t,e){let s=e.parentInfo&&Vt(t,e.parentInfo);if(!s)return t;$t.currentNode=s;for(let t=$t.firstChild(),s=0;t;t=$t.nextSibling())if(e.parentIndex===s++)return t}function Ut(t,e,s,n){n.id&&(e[n.id]=s)}function Xt(t,e,s){if(s.events&&s.events.length)for(let n,r=0,i=s.events;r<i.length&&(n=i[r]);r++)t._addMethodEventListenerToNode(e,n.name,n.value,t)}function Wt(t,e,s){s.templateInfo&&(e._templateInfo=s.templateInfo)}const Gt=d((t=>class extends t{static _parseTemplate(t,e){if(!t._templateInfo){let e=t._templateInfo={};e.nodeInfoList=[],e.stripWhiteSpace=!0,this._parseTemplateContent(t,e,{parent:null})}return t._templateInfo}static _parseTemplateContent(t,e,s){return this._parseTemplateNode(t.content,e,s)}static _parseTemplateNode(t,e,s){let n,r=t;return"template"!=r.localName||r.hasAttribute("preserve-content")?"slot"===r.localName&&(e.hasInsertionPoint=!0):n=this._parseTemplateNestedTemplate(r,e,s)||n,$t.currentNode=r,$t.firstChild()&&(n=this._parseTemplateChildNodes(r,e,s)||n),r.hasAttributes&&r.hasAttributes()&&(n=this._parseTemplateNodeAttributes(r,e,s)||n),n}static _parseTemplateChildNodes(t,e,s){if("script"!==t.localName&&"style"!==t.localName){$t.currentNode=t;for(let n,r=$t.firstChild(),i=0;r;r=n){if("template"==r.localName&&(r=Jt(r)),$t.currentNode=r,n=$t.nextSibling(),r.nodeType===Node.TEXT_NODE){let s=n;for(;s&&s.nodeType===Node.TEXT_NODE;)r.textContent+=s.textContent,n=$t.nextSibling(),t.removeChild(s),s=n;if(e.stripWhiteSpace&&!r.textContent.trim()){t.removeChild(r);continue}}let o={parentIndex:i,parentInfo:s};this._parseTemplateNode(r,e,o)&&(o.infoIndex=e.nodeInfoList.push(o)-1),$t.currentNode=r,$t.parentNode()&&i++}}}static _parseTemplateNestedTemplate(t,e,s){let n=this._parseTemplate(t,e);return(n.content=t.content.ownerDocument.createDocumentFragment()).appendChild(t.content),s.templateInfo=n,!0}static _parseTemplateNodeAttributes(t,e,s){let n=!1,r=Array.from(t.attributes);for(let i,o=r.length-1;i=r[o];o--)n=this._parseTemplateNodeAttribute(t,e,s,i.name,i.value)||n;return n}static _parseTemplateNodeAttribute(t,e,s,n,r){return"on-"===n.slice(0,3)?(t.removeAttribute(n),s.events=s.events||[],s.events.push({name:n.slice(3),value:r}),!0):"id"===n&&(s.id=r,!0)}static _contentForTemplate(t){let e=t._templateInfo;return e&&e.content||t.content}_stampTemplate(t){t&&!t.content&&window.HTMLTemplateElement&&HTMLTemplateElement.decorate&&HTMLTemplateElement.decorate(t);let e=this.constructor._parseTemplate(t),s=e.nodeInfoList,n=e.content||t.content,r=document.importNode(n,!0);r.__noInsertionPoint=!e.hasInsertionPoint;let i=r.nodeList=new Array(s.length);r.$={};for(let t,e=0,n=s.length;e<n&&(t=s[e]);e++){let s=i[e]=Vt(r,t);Ut(0,r.$,s,t),Wt(0,s,t),Xt(this,s,t)}return r=r,r}_addMethodEventListenerToNode(t,e,s,n){let r=function(t,e,s){return t=t._methodHost||t,function(e){t[s]?t[s](e,e.detail):console.warn("listener method `"+s+"` not defined")}}(n=n||t,0,s);return this._addEventListenerToNode(t,e,r),r}_addEventListenerToNode(t,e,s){t.addEventListener(e,s)}_removeEventListenerFromNode(t,e,s){t.removeEventListener(e,s)}}));let Zt=0;const Kt={COMPUTE:"__computeEffects",REFLECT:"__reflectEffects",NOTIFY:"__notifyEffects",PROPAGATE:"__propagateEffects",OBSERVE:"__observeEffects",READ_ONLY:"__readOnly"},Qt=/[A-Z]/;function te(t,e){let s=t[e];if(s){if(!t.hasOwnProperty(e)){s=t[e]=Object.create(t[e]);for(let t in s){let e=s[t],n=s[t]=Array(e.length);for(let t=0;t<e.length;t++)n[t]=e[t]}}}else s=t[e]={};return s}function ee(t,e,s,n,r,i){if(e){let o=!1,a=Zt++;for(let l in s)se(t,e,a,l,s,n,r,i)&&(o=!0);return o}return!1}function se(t,e,s,n,r,i,o,a){let l=!1,h=e[o?wt(n):n];if(h)for(let e,d=0,c=h.length;d<c&&(e=h[d]);d++)e.info&&e.info.lastRun===s||o&&!ne(n,e.trigger)||(e.info&&(e.info.lastRun=s),e.fn(t,n,r,i,e.info,o,a),l=!0);return l}function ne(t,e){if(e){let s=e.name;return s==t||!(!e.structured||!Et(s,t))||!(!e.wildcard||!Tt(s,t))}return!0}function re(t,e,s,n,r){let i="string"==typeof r.method?t[r.method]:r.method,o=r.property;i?i.call(t,t.__data[o],n[o]):r.dynamicFn||console.warn("observer method `"+r.method+"` not defined")}function ie(t,e,s){let n=wt(e);if(n!==e){return oe(t,Ft(n)+"-changed",s[e],e),!0}return!1}function oe(t,e,s,n){let r={value:s,queueProperty:!0};n&&(r.path=n),E(t).dispatchEvent(new CustomEvent(e,{detail:r}))}function ae(t,e,s,n,r,i){let o=(i?wt(e):e)!=e?e:null,a=o?It(t,o):t.__data[e];o&&void 0===a&&(a=s[e]),oe(t,r.eventName,a,o)}function le(t,e,s,n,r){let i=t.__data[e];w&&(i=w(i,r.attrName,"attribute",t)),t._propertyToAttribute(e,r.attrName,i)}function he(t,e,s,n,r){let i=me(t,e,s,n,r),o=r.methodInfo;t.__dataHasAccessor&&t.__dataHasAccessor[o]?t._setPendingProperty(o,i,!0):t[o]=i}function de(t,e,s,n,r,i,o){s.bindings=s.bindings||[];let a={kind:n,target:r,parts:i,literal:o,isCompound:1!==i.length};if(s.bindings.push(a),function(t){return Boolean(t.target)&&"attribute"!=t.kind&&"text"!=t.kind&&!t.isCompound&&"{"===t.parts[0].mode}(a)){let{event:t,negate:e}=a.parts[0];a.listenerEvent=t||Ft(r)+"-changed",a.listenerNegate=e}let l=e.nodeInfoList.length;for(let s=0;s<a.parts.length;s++){let n=a.parts[s];n.compoundIndex=s,ce(t,e,a,n,l)}}function ce(t,e,s,n,r){if(!n.literal)if("attribute"===s.kind&&"-"===s.target[0])console.warn("Cannot set attribute "+s.target+' because "-" is not a valid attribute starting character');else{let i=n.dependencies,o={index:r,binding:s,part:n,evaluator:t};for(let s=0;s<i.length;s++){let n=i[s];"string"==typeof n&&(n=Ce(n),n.wildcard=!0),t._addTemplatePropertyEffect(e,n.rootProperty,{fn:ue,info:o,trigger:n})}}}function ue(t,e,s,n,r,i,o){let a=o[r.index],l=r.binding,h=r.part;if(i&&h.source&&e.length>h.source.length&&"property"==l.kind&&!l.isCompound&&a.__isPropertyEffectsClient&&a.__dataHasAccessor&&a.__dataHasAccessor[l.target]){let n=s[e];e=Ot(h.source,l.target,e),a._setPendingPropertyOrPath(e,n,!1,!0)&&t._enqueueClient(a)}else{!function(t,e,s,n,r){r=function(t,e,s,n){if(s.isCompound){let r=t.__dataCompoundStorage[s.target];r[n.compoundIndex]=e,e=r.join("")}"attribute"!==s.kind&&("textContent"!==s.target&&("value"!==s.target||"input"!==t.localName&&"textarea"!==t.localName)||(e=null==e?"":e));return e}(e,r,s,n),w&&(r=w(r,s.target,s.kind,e));if("attribute"==s.kind)t._valueToNodeAttribute(e,r,s.target);else{let n=s.target;e.__isPropertyEffectsClient&&e.__dataHasAccessor&&e.__dataHasAccessor[n]?e[Kt.READ_ONLY]&&e[Kt.READ_ONLY][n]||e._setPendingProperty(n,r)&&t._enqueueClient(e):t._setUnmanagedPropertyToNode(e,n,r)}}(t,a,l,h,r.evaluator._evaluateBinding(t,h,e,s,n,i))}}function pe(t,e){if(e.isCompound){let s=t.__dataCompoundStorage||(t.__dataCompoundStorage={}),n=e.parts,r=new Array(n.length);for(let t=0;t<n.length;t++)r[t]=n[t].literal;let i=e.target;s[i]=r,e.literal&&"property"==e.kind&&(t[i]=e.literal)}}function _e(t,e,s){if(s.listenerEvent){let n=s.parts[0];t.addEventListener(s.listenerEvent,(function(t){!function(t,e,s,n,r){let i,o=t.detail,a=o&&o.path;a?(n=Ot(s,n,a),i=o&&o.value):i=t.currentTarget[s],i=r?!i:i,e[Kt.READ_ONLY]&&e[Kt.READ_ONLY][n]||!e._setPendingPropertyOrPath(n,i,!0,Boolean(a))||o&&o.queueProperty||e._invalidateProperties()}(t,e,s.target,n.source,n.negate)}))}}function fe(t,e,s,n,r,i){i=e.static||i&&("object"!=typeof i||i[e.methodName]);let o={methodName:e.methodName,args:e.args,methodInfo:r,dynamicFn:i};for(let r,i=0;i<e.args.length&&(r=e.args[i]);i++)r.literal||t._addPropertyEffect(r.rootProperty,s,{fn:n,info:o,trigger:r});i&&t._addPropertyEffect(e.methodName,s,{fn:n,info:o})}function me(t,e,s,n,r){let i=t._methodHost||t,o=i[r.methodName];if(o){let n=t._marshalArgs(r.args,e,s);return o.apply(i,n)}r.dynamicFn||console.warn("method `"+r.methodName+"` not defined")}const ye=[],ge=new RegExp("(\\[\\[|{{)\\s*(?:(!)\\s*)?((?:[a-zA-Z_$][\\w.:$\\-*]*)\\s*(?:\\(\\s*(?:(?:(?:((?:[a-zA-Z_$][\\w.:$\\-*]*)|(?:[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|(?:(?:'(?:[^'\\\\]|\\\\.)*')|(?:\"(?:[^\"\\\\]|\\\\.)*\")))\\s*)(?:,\\s*(?:((?:[a-zA-Z_$][\\w.:$\\-*]*)|(?:[-+]?[0-9]*\\.?[0-9]+(?:[eE][-+]?[0-9]+)?)|(?:(?:'(?:[^'\\\\]|\\\\.)*')|(?:\"(?:[^\"\\\\]|\\\\.)*\")))\\s*))*)?)\\)\\s*)?)(?:]]|}})","g");function be(t){let e="";for(let s=0;s<t.length;s++){e+=t[s].literal||""}return e}function Pe(t){let e=t.match(/([^\s]+?)\(([\s\S]*)\)/);if(e){let t={methodName:e[1],static:!0,args:ye};if(e[2].trim()){return function(t,e){return e.args=t.map((function(t){let s=Ce(t);return s.literal||(e.static=!1),s}),this),e}(e[2].replace(/\\,/g,"&comma;").split(","),t)}return t}return null}function Ce(t){let e=t.trim().replace(/&comma;/g,",").replace(/\\(.)/g,"$1"),s={name:e,value:"",literal:!1},n=e[0];switch("-"===n&&(n=e[1]),n>="0"&&n<="9"&&(n="#"),n){case"'":case'"':s.value=e.slice(1,-1),s.literal=!0;break;case"#":s.value=Number(e),s.literal=!0}return s.literal||(s.rootProperty=wt(e),s.structured=St(e),s.structured&&(s.wildcard=".*"==e.slice(-2),s.wildcard&&(s.name=e.slice(0,-2)))),s}function ve(t,e,s){let n=It(t,s);return void 0===n&&(n=e[s]),n}function Se(t,e,s,n){t.notifyPath(s+".splices",{indexSplices:n}),t.notifyPath(s+".length",e.length)}function we(t,e,s,n,r,i){Se(t,e,s,[{index:n,addedCount:r,removed:i,object:e,type:"splice"}])}const Ee=d((t=>{const e=Gt(qt(t));return class extends e{constructor(){super(),this.__isPropertyEffectsClient=!0,this.__dataCounter=0,this.__dataClientsReady,this.__dataPendingClients,this.__dataToNotify,this.__dataLinkedPaths,this.__dataHasPaths,this.__dataCompoundStorage,this.__dataHost,this.__dataTemp,this.__dataClientsInitialized,this.__data,this.__dataPending,this.__dataOld,this.__computeEffects,this.__reflectEffects,this.__notifyEffects,this.__propagateEffects,this.__observeEffects,this.__readOnly,this.__templateInfo}get PROPERTY_EFFECT_TYPES(){return Kt}_initializeProperties(){super._initializeProperties(),Te.registerHost(this),this.__dataClientsReady=!1,this.__dataPendingClients=null,this.__dataToNotify=null,this.__dataLinkedPaths=null,this.__dataHasPaths=!1,this.__dataCompoundStorage=this.__dataCompoundStorage||null,this.__dataHost=this.__dataHost||null,this.__dataTemp={},this.__dataClientsInitialized=!1}_initializeProtoProperties(t){this.__data=Object.create(t),this.__dataPending=Object.create(t),this.__dataOld={}}_initializeInstanceProperties(t){let e=this[Kt.READ_ONLY];for(let s in t)e&&e[s]||(this.__dataPending=this.__dataPending||{},this.__dataOld=this.__dataOld||{},this.__data[s]=this.__dataPending[s]=t[s])}_addPropertyEffect(t,e,s){this._createPropertyAccessor(t,e==Kt.READ_ONLY);let n=te(this,e)[t];n||(n=this[e][t]=[]),n.push(s)}_removePropertyEffect(t,e,s){let n=te(this,e)[t],r=n.indexOf(s);r>=0&&n.splice(r,1)}_hasPropertyEffect(t,e){let s=this[e];return Boolean(s&&s[t])}_hasReadOnlyEffect(t){return this._hasPropertyEffect(t,Kt.READ_ONLY)}_hasNotifyEffect(t){return this._hasPropertyEffect(t,Kt.NOTIFY)}_hasReflectEffect(t){return this._hasPropertyEffect(t,Kt.REFLECT)}_hasComputedEffect(t){return this._hasPropertyEffect(t,Kt.COMPUTE)}_setPendingPropertyOrPath(t,e,s,n){if(n||wt(Array.isArray(t)?t[0]:t)!==t){if(!n){let s=It(this,t);if(!(t=Mt(this,t,e))||!super._shouldPropertyChange(t,e,s))return!1}if(this.__dataHasPaths=!0,this._setPendingProperty(t,e,s))return function(t,e,s){let n=t.__dataLinkedPaths;if(n){let r;for(let i in n){let o=n[i];Tt(i,e)?(r=Ot(i,o,e),t._setPendingPropertyOrPath(r,s,!0,!0)):Tt(o,e)&&(r=Ot(o,i,e),t._setPendingPropertyOrPath(r,s,!0,!0))}}}(this,t,e),!0}else{if(this.__dataHasAccessor&&this.__dataHasAccessor[t])return this._setPendingProperty(t,e,s);this[t]=e}return!1}_setUnmanagedPropertyToNode(t,e,s){s===t[e]&&"object"!=typeof s||(t[e]=s)}_setPendingProperty(t,e,s){let n=this.__dataHasPaths&&St(t),r=n?this.__dataTemp:this.__data;return!!this._shouldPropertyChange(t,e,r[t])&&(this.__dataPending||(this.__dataPending={},this.__dataOld={}),t in this.__dataOld||(this.__dataOld[t]=this.__data[t]),n?this.__dataTemp[t]=e:this.__data[t]=e,this.__dataPending[t]=e,(n||this[Kt.NOTIFY]&&this[Kt.NOTIFY][t])&&(this.__dataToNotify=this.__dataToNotify||{},this.__dataToNotify[t]=s),!0)}_setProperty(t,e){this._setPendingProperty(t,e,!0)&&this._invalidateProperties()}_invalidateProperties(){this.__dataReady&&this._flushProperties()}_enqueueClient(t){this.__dataPendingClients=this.__dataPendingClients||[],t!==this&&this.__dataPendingClients.push(t)}_flushProperties(){this.__dataCounter++,super._flushProperties(),this.__dataCounter--}_flushClients(){this.__dataClientsReady?this.__enableOrFlushClients():(this.__dataClientsReady=!0,this._readyClients(),this.__dataReady=!0)}__enableOrFlushClients(){let t=this.__dataPendingClients;if(t){this.__dataPendingClients=null;for(let e=0;e<t.length;e++){let s=t[e];s.__dataEnabled?s.__dataPending&&s._flushProperties():s._enableProperties()}}}_readyClients(){this.__enableOrFlushClients()}setProperties(t,e){for(let s in t)!e&&this[Kt.READ_ONLY]&&this[Kt.READ_ONLY][s]||this._setPendingPropertyOrPath(s,t[s],!0);this._invalidateProperties()}ready(){this._flushProperties(),this.__dataClientsReady||this._flushClients(),this.__dataPending&&this._flushProperties()}_propertiesChanged(t,e,s){let n=this.__dataHasPaths;this.__dataHasPaths=!1,function(t,e,s,n){let r=t[Kt.COMPUTE];if(r){let i=e;for(;ee(t,r,i,s,n);)Object.assign(s,t.__dataOld),Object.assign(e,t.__dataPending),i=t.__dataPending,t.__dataPending=null}}(this,e,s,n);let r=this.__dataToNotify;this.__dataToNotify=null,this._propagatePropertyChanges(e,s,n),this._flushClients(),ee(this,this[Kt.REFLECT],e,s,n),ee(this,this[Kt.OBSERVE],e,s,n),r&&function(t,e,s,n,r){let i,o,a=t[Kt.NOTIFY],l=Zt++;for(let o in e)e[o]&&(a&&se(t,a,l,o,s,n,r)||r&&ie(t,o,s))&&(i=!0);i&&(o=t.__dataHost)&&o._invalidateProperties&&o._invalidateProperties()}(this,r,e,s,n),1==this.__dataCounter&&(this.__dataTemp={})}_propagatePropertyChanges(t,e,s){this[Kt.PROPAGATE]&&ee(this,this[Kt.PROPAGATE],t,e,s);let n=this.__templateInfo;for(;n;)ee(this,n.propertyEffects,t,e,s,n.nodeList),n=n.nextTemplateInfo}linkPaths(t,e){t=xt(t),e=xt(e),this.__dataLinkedPaths=this.__dataLinkedPaths||{},this.__dataLinkedPaths[t]=e}unlinkPaths(t){t=xt(t),this.__dataLinkedPaths&&delete this.__dataLinkedPaths[t]}notifySplices(t,e){let s={path:""};Se(this,It(this,t,s),s.path,e)}get(t,e){return It(e||this,t)}set(t,e,s){s?Mt(s,t,e):this[Kt.READ_ONLY]&&this[Kt.READ_ONLY][t]||this._setPendingPropertyOrPath(t,e,!0)&&this._invalidateProperties()}push(t,...e){let s={path:""},n=It(this,t,s),r=n.length,i=n.push(...e);return e.length&&we(this,n,s.path,r,e.length,[]),i}pop(t){let e={path:""},s=It(this,t,e),n=Boolean(s.length),r=s.pop();return n&&we(this,s,e.path,s.length,0,[r]),r}splice(t,e,s,...n){let r,i={path:""},o=It(this,t,i);return e<0?e=o.length-Math.floor(-e):e&&(e=Math.floor(e)),r=2===arguments.length?o.splice(e):o.splice(e,s,...n),(n.length||r.length)&&we(this,o,i.path,e,n.length,r),r}shift(t){let e={path:""},s=It(this,t,e),n=Boolean(s.length),r=s.shift();return n&&we(this,s,e.path,0,0,[r]),r}unshift(t,...e){let s={path:""},n=It(this,t,s),r=n.unshift(...e);return e.length&&we(this,n,s.path,0,e.length,[]),r}notifyPath(t,e){let s;if(1==arguments.length){let n={path:""};e=It(this,t,n),s=n.path}else s=Array.isArray(t)?xt(t):t;this._setPendingPropertyOrPath(s,e,!0,!0)&&this._invalidateProperties()}_createReadOnlyProperty(t,e){var s;this._addPropertyEffect(t,Kt.READ_ONLY),e&&(this["_set"+(s=t,s[0].toUpperCase()+s.substring(1))]=function(e){this._setProperty(t,e)})}_createPropertyObserver(t,e,s){let n={property:t,method:e,dynamicFn:Boolean(s)};this._addPropertyEffect(t,Kt.OBSERVE,{fn:re,info:n,trigger:{name:t}}),s&&this._addPropertyEffect(e,Kt.OBSERVE,{fn:re,info:n,trigger:{name:e}})}_createMethodObserver(t,e){let s=Pe(t);if(!s)throw new Error("Malformed observer expression '"+t+"'");fe(this,s,Kt.OBSERVE,me,null,e)}_createNotifyingProperty(t){this._addPropertyEffect(t,Kt.NOTIFY,{fn:ae,info:{eventName:Ft(t)+"-changed",property:t}})}_createReflectedProperty(t){let e=this.constructor.attributeNameForProperty(t);"-"===e[0]?console.warn("Property "+t+" cannot be reflected to attribute "+e+' because "-" is not a valid starting attribute name. Use a lowercase first letter for the property instead.'):this._addPropertyEffect(t,Kt.REFLECT,{fn:le,info:{attrName:e}})}_createComputedProperty(t,e,s){let n=Pe(e);if(!n)throw new Error("Malformed computed expression '"+e+"'");fe(this,n,Kt.COMPUTE,he,t,s)}_marshalArgs(t,e,s){const n=this.__data,r=[];for(let i=0,o=t.length;i<o;i++){let{name:o,structured:a,wildcard:l,value:h,literal:d}=t[i];if(!d)if(l){const t=Tt(o,e),r=ve(n,s,t?e:o);h={path:t?e:o,value:r,base:t?It(n,o):r}}else h=a?ve(n,s,o):n[o];r[i]=h}return r}static addPropertyEffect(t,e,s){this.prototype._addPropertyEffect(t,e,s)}static createPropertyObserver(t,e,s){this.prototype._createPropertyObserver(t,e,s)}static createMethodObserver(t,e){this.prototype._createMethodObserver(t,e)}static createNotifyingProperty(t){this.prototype._createNotifyingProperty(t)}static createReadOnlyProperty(t,e){this.prototype._createReadOnlyProperty(t,e)}static createReflectedProperty(t){this.prototype._createReflectedProperty(t)}static createComputedProperty(t,e,s){this.prototype._createComputedProperty(t,e,s)}static bindTemplate(t){return this.prototype._bindTemplate(t)}_bindTemplate(t,e){let s=this.constructor._parseTemplate(t),n=this.__templateInfo==s;if(!n)for(let t in s.propertyEffects)this._createPropertyAccessor(t);if(e&&(s=Object.create(s),s.wasPreBound=n,!n&&this.__templateInfo)){let t=this.__templateInfoLast||this.__templateInfo;return this.__templateInfoLast=t.nextTemplateInfo=s,s.previousTemplateInfo=t,s}return this.__templateInfo=s}static _addTemplatePropertyEffect(t,e,s){(t.hostProps=t.hostProps||{})[e]=!0;let n=t.propertyEffects=t.propertyEffects||{};(n[e]=n[e]||[]).push(s)}_stampTemplate(t){Te.beginHosting(this);let e=super._stampTemplate(t);Te.endHosting(this);let s=this._bindTemplate(t,!0);if(s.nodeList=e.nodeList,!s.wasPreBound){let t=s.childNodes=[];for(let s=e.firstChild;s;s=s.nextSibling)t.push(s)}return e.templateInfo=s,function(t,e){let{nodeList:s,nodeInfoList:n}=e;if(n.length)for(let e=0;e<n.length;e++){let r=n[e],i=s[e],o=r.bindings;if(o)for(let e=0;e<o.length;e++){let s=o[e];pe(i,s),_e(i,t,s)}i.__dataHost=t}}(this,s),this.__dataReady&&ee(this,s.propertyEffects,this.__data,null,!1,s.nodeList),e}_removeBoundDom(t){let e=t.templateInfo;e.previousTemplateInfo&&(e.previousTemplateInfo.nextTemplateInfo=e.nextTemplateInfo),e.nextTemplateInfo&&(e.nextTemplateInfo.previousTemplateInfo=e.previousTemplateInfo),this.__templateInfoLast==e&&(this.__templateInfoLast=e.previousTemplateInfo),e.previousTemplateInfo=e.nextTemplateInfo=null;let s=e.childNodes;for(let t=0;t<s.length;t++){let e=s[t];e.parentNode.removeChild(e)}}static _parseTemplateNode(t,e,s){let n=super._parseTemplateNode(t,e,s);if(t.nodeType===Node.TEXT_NODE){let r=this._parseBindings(t.textContent,e);r&&(t.textContent=be(r)||" ",de(this,e,s,"text","textContent",r),n=!0)}return n}static _parseTemplateNodeAttribute(t,e,s,n,r){let i=this._parseBindings(r,e);if(i){let r=n,o="property";Qt.test(n)?o="attribute":"$"==n[n.length-1]&&(n=n.slice(0,-1),o="attribute");let a=be(i);return a&&"attribute"==o&&("class"==n&&t.hasAttribute("class")&&(a+=" "+t.getAttribute(n)),t.setAttribute(n,a)),"input"===t.localName&&"value"===r&&t.setAttribute(r,""),t.removeAttribute(r),"property"===o&&(n=Dt(n)),de(this,e,s,o,n,i,a),!0}return super._parseTemplateNodeAttribute(t,e,s,n,r)}static _parseTemplateNestedTemplate(t,e,s){let n=super._parseTemplateNestedTemplate(t,e,s),r=s.templateInfo.hostProps;for(let t in r){de(this,e,s,"property","_host_"+t,[{mode:"{",source:t,dependencies:[t]}])}return n}static _parseBindings(t,e){let s,n=[],r=0;for(;null!==(s=ge.exec(t));){s.index>r&&n.push({literal:t.slice(r,s.index)});let i=s[1][0],o=Boolean(s[2]),a=s[3].trim(),l=!1,h="",d=-1;"{"==i&&(d=a.indexOf("::"))>0&&(h=a.substring(d+2),a=a.substring(0,d),l=!0);let c=Pe(a),u=[];if(c){let{args:t,methodName:s}=c;for(let e=0;e<t.length;e++){let s=t[e];s.literal||u.push(s)}let n=e.dynamicFns;(n&&n[s]||c.static)&&(u.push(s),c.dynamicFn=!0)}else u.push(a);n.push({source:a,mode:i,negate:o,customEvent:l,signature:c,dependencies:u,event:h}),r=ge.lastIndex}if(r&&r<t.length){let e=t.substring(r);e&&n.push({literal:e})}return n.length?n:null}static _evaluateBinding(t,e,s,n,r,i){let o;return o=e.signature?me(t,s,n,0,e.signature):s!=e.source?It(t,e.source):i&&St(s)?It(t,s):t.__data[s],e.negate&&(o=!o),o}}}));const Te=new class{constructor(){this.stack=[]}registerHost(t){if(this.stack.length){this.stack[this.stack.length-1]._enqueueClient(t)}}beginHosting(t){this.stack.push(t)}endHosting(t){let e=this.stack.length;e&&this.stack[e-1]==t&&this.stack.pop()}};const Oe=d((t=>{const e=zt(t);function s(t){const e=Object.getPrototypeOf(t);return e.prototype instanceof r?e:null}function n(t){if(!t.hasOwnProperty(JSCompiler_renameProperty("__ownProperties",t))){let e=null;if(t.hasOwnProperty(JSCompiler_renameProperty("properties",t))){const s=t.properties;s&&(e=function(t){const e={};for(let s in t){const n=t[s];e[s]="function"==typeof n?{type:n}:n}return e}(s))}t.__ownProperties=e}return t.__ownProperties}class r extends e{static get observedAttributes(){if(!this.hasOwnProperty("__observedAttributes")){this.prototype;const t=this._properties;this.__observedAttributes=t?Object.keys(t).map((t=>this.attributeNameForProperty(t))):[]}return this.__observedAttributes}static finalize(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__finalized",this))){const t=s(this);t&&t.finalize(),this.__finalized=!0,this._finalizeClass()}}static _finalizeClass(){const t=n(this);t&&this.createProperties(t)}static get _properties(){if(!this.hasOwnProperty(JSCompiler_renameProperty("__properties",this))){const t=s(this);this.__properties=Object.assign({},t&&t._properties,n(this))}return this.__properties}static typeForProperty(t){const e=this._properties[t];return e&&e.type}_initializeProperties(){this.constructor.finalize(),super._initializeProperties()}connectedCallback(){super.connectedCallback&&super.connectedCallback(),this._enableProperties()}disconnectedCallback(){super.disconnectedCallback&&super.disconnectedCallback()}}return r})),Ne=window.ShadyCSS&&window.ShadyCSS.cssBuild,xe=d((t=>{const e=Oe(Ee(t));function s(t,e,s,n){s.computed&&(s.readOnly=!0),s.computed&&(t._hasReadOnlyEffect(e)?console.warn(`Cannot redefine computed property '${e}'.`):t._createComputedProperty(e,s.computed,n)),s.readOnly&&!t._hasReadOnlyEffect(e)?t._createReadOnlyProperty(e,!s.computed):!1===s.readOnly&&t._hasReadOnlyEffect(e)&&console.warn(`Cannot make readOnly property '${e}' non-readOnly.`),s.reflectToAttribute&&!t._hasReflectEffect(e)?t._createReflectedProperty(e):!1===s.reflectToAttribute&&t._hasReflectEffect(e)&&console.warn(`Cannot make reflected property '${e}' non-reflected.`),s.notify&&!t._hasNotifyEffect(e)?t._createNotifyingProperty(e):!1===s.notify&&t._hasNotifyEffect(e)&&console.warn(`Cannot make notify property '${e}' non-notify.`),s.observer&&t._createPropertyObserver(e,s.observer,n[s.observer]),t._addPropertyToAttributeMap(e)}function n(t,e,s,n){if(!Ne){const r=e.content.querySelectorAll("style"),i=Pt(e),o=function(t){let e=mt(t);return e?Ct(e):[]}(s),a=e.content.firstElementChild;for(let s=0;s<o.length;s++){let r=o[s];r.textContent=t._processStyleText(r.textContent,n),e.content.insertBefore(r,a)}let l=0;for(let e=0;e<i.length;e++){let s=i[e],o=r[l];o!==s?(s=s.cloneNode(!0),o.parentNode.insertBefore(s,o)):l++,s.textContent=t._processStyleText(s.textContent,n)}}window.ShadyCSS&&window.ShadyCSS.prepareTemplate(e,s)}return class extends e{static get polymerElementVersion(){return"3.2.0"}static _finalizeClass(){super._finalizeClass();const t=((e=this).hasOwnProperty(JSCompiler_renameProperty("__ownObservers",e))||(e.__ownObservers=e.hasOwnProperty(JSCompiler_renameProperty("observers",e))?e.observers:null),e.__ownObservers);var e;t&&this.createObservers(t,this._properties),this._prepareTemplate()}static _prepareTemplate(){let t=this.template;t&&("string"==typeof t?(console.error("template getter must return HTMLTemplateElement"),t=null):t=t.cloneNode(!0)),this.prototype._template=t}static createProperties(t){for(let e in t)s(this.prototype,e,t[e],t)}static createObservers(t,e){const s=this.prototype;for(let n=0;n<t.length;n++)s._createMethodObserver(t[n],e)}static get template(){return this.hasOwnProperty(JSCompiler_renameProperty("_template",this))||(this._template=this.prototype.hasOwnProperty(JSCompiler_renameProperty("_template",this.prototype))?this.prototype._template:function(t){let e=null;return t&&(e=ft.import(t,"template")),e}(this.is)||Object.getPrototypeOf(this.prototype).constructor.template),this._template}static set template(t){this._template=t}static get importPath(){if(!this.hasOwnProperty(JSCompiler_renameProperty("_importPath",this))){const t=this.importMeta;if(t)this._importPath=C(t.url);else{const t=ft.import(this.is);this._importPath=t&&t.assetpath||Object.getPrototypeOf(this.prototype).constructor.importPath}}return this._importPath}constructor(){super(),this._template,this._importPath,this.rootPath,this.importPath,this.root,this.$}_initializeProperties(){this.constructor.finalize(),this.constructor._finalizeTemplate(this.localName),super._initializeProperties(),this.rootPath=S,this.importPath=this.constructor.importPath;let t=function(t){if(!t.hasOwnProperty(JSCompiler_renameProperty("__propertyDefaults",t))){t.__propertyDefaults=null;let e=t._properties;for(let s in e){let n=e[s];"value"in n&&(t.__propertyDefaults=t.__propertyDefaults||{},t.__propertyDefaults[s]=n)}}return t.__propertyDefaults}(this.constructor);if(t)for(let e in t){let s=t[e];if(!this.hasOwnProperty(e)){let t="function"==typeof s.value?s.value.call(this):s.value;this._hasAccessor(e)?this._setPendingProperty(e,t,!0):this[e]=t}}}static _processStyleText(t,e){return P(t,e)}static _finalizeTemplate(t){const e=this.prototype._template;if(e&&!e.__polymerFinalized){e.__polymerFinalized=!0;const s=this.importPath;n(this,e,t,s?b(s):""),this.prototype._bindTemplate(e)}}connectedCallback(){window.ShadyCSS&&this._template&&window.ShadyCSS.styleElement(this),super.connectedCallback()}ready(){this._template&&(this.root=this._stampTemplate(this._template),this.$=this.root.$),super.ready()}_readyClients(){this._template&&(this.root=this._attachDom(this.root)),super._readyClients()}_attachDom(t){const e=E(this);if(e.attachShadow)return t?(e.shadowRoot||e.attachShadow({mode:"open"}),e.shadowRoot.appendChild(t),e.shadowRoot):null;throw new Error("ShadowDOM not available. PolymerElement can create dom as children instead of in ShadowDOM by setting `this.root = this;` before `ready`.")}updateStyles(t){window.ShadyCSS&&window.ShadyCSS.styleSubtree(this,t)}resolveUrl(t,e){return!e&&this.importPath&&(e=b(this.importPath)),b(t,e)}static _parseTemplateContent(t,e,s){return e.dynamicFns=e.dynamicFns||this._properties,super._parseTemplateContent(t,e,s)}static _addTemplatePropertyEffect(t,e,s){return super._addTemplatePropertyEffect(t,e,s)}}}));class Ae{constructor(t){this.value=t.toString()}toString(){return this.value}}function Ie(t){if(t instanceof HTMLTemplateElement)return t.innerHTML;if(t instanceof Ae)return function(t){if(t instanceof Ae)return t.value;throw new Error("non-literal value passed to Polymer's htmlLiteral function: "+t)}(t);throw new Error("non-template value passed to Polymer's html function: "+t)}const Me=function(t,...e){const s=document.createElement("template");return s.innerHTML=e.reduce(((e,s,n)=>e+Ie(s)+t[n+1]),t[0]),s},Re=xe(HTMLElement);function Le(t,e,s,n,r){let i;r&&(i="object"==typeof s&&null!==s,i&&(n=t.__dataTemp[e]));let o=n!==s&&(n==n||s==s);return i&&o&&(t.__dataTemp[e]=s),o}const ke=d((t=>class extends t{_shouldPropertyChange(t,e,s){return Le(this,t,e,s,!0)}})),De=d((t=>class extends t{static get properties(){return{mutableData:Boolean}}_shouldPropertyChange(t,e,s){return Le(this,t,e,s,this.mutableData)}}));ke._mutablePropertyChange=Le;let Fe=null;function He(){return Fe}He.prototype=Object.create(HTMLTemplateElement.prototype,{constructor:{value:He,writable:!0}});const ze=Ee(He),je=ke(ze);const Be=Ee(class{});class qe extends Be{constructor(t){super(),this._configureProperties(t),this.root=this._stampTemplate(this.__dataHost);let e=this.children=[];for(let t=this.root.firstChild;t;t=t.nextSibling)e.push(t),t.__templatizeInstance=this;this.__templatizeOwner&&this.__templatizeOwner.__hideTemplateChildren__&&this._showHideChildren(!0);let s=this.__templatizeOptions;(t&&s.instanceProps||!s.instanceProps)&&this._enableProperties()}_configureProperties(t){if(this.__templatizeOptions.forwardHostProp)for(let t in this.__hostProps)this._setPendingProperty(t,this.__dataHost["_host_"+t]);for(let e in t)this._setPendingProperty(e,t[e])}forwardHostProp(t,e){this._setPendingPropertyOrPath(t,e,!1,!0)&&this.__dataHost._enqueueClient(this)}_addEventListenerToNode(t,e,s){if(this._methodHost&&this.__templatizeOptions.parentModel)this._methodHost._addEventListenerToNode(t,e,(t=>{t.model=this,s(t)}));else{let n=this.__dataHost.__dataHost;n&&n._addEventListenerToNode(t,e,s)}}_showHideChildren(t){let e=this.children;for(let s=0;s<e.length;s++){let n=e[s];if(Boolean(t)!=Boolean(n.__hideTemplateChildren__))if(n.nodeType===Node.TEXT_NODE)t?(n.__polymerTextContent__=n.textContent,n.textContent=""):n.textContent=n.__polymerTextContent__;else if("slot"===n.localName)if(t)n.__polymerReplaced__=document.createComment("hidden-slot"),E(E(n).parentNode).replaceChild(n.__polymerReplaced__,n);else{const t=n.__polymerReplaced__;t&&E(E(t).parentNode).replaceChild(n,t)}else n.style&&(t?(n.__polymerDisplay__=n.style.display,n.style.display="none"):n.style.display=n.__polymerDisplay__);n.__hideTemplateChildren__=t,n._showHideChildren&&n._showHideChildren(t)}}_setUnmanagedPropertyToNode(t,e,s){t.__hideTemplateChildren__&&t.nodeType==Node.TEXT_NODE&&"textContent"==e?t.__polymerTextContent__=s:super._setUnmanagedPropertyToNode(t,e,s)}get parentModel(){let t=this.__parentModel;if(!t){let e;t=this;do{t=t.__dataHost.__dataHost}while((e=t.__templatizeOptions)&&!e.parentModel);this.__parentModel=t}return t}dispatchEvent(t){return!0}}qe.prototype.__dataHost,qe.prototype.__templatizeOptions,qe.prototype._methodHost,qe.prototype.__templatizeOwner,qe.prototype.__hostProps;const $e=ke(qe);function Ye(t,e,s){let n=s.mutableData?$e:qe;Xe.mixin&&(n=Xe.mixin(n));let r=class extends n{};return r.prototype.__templatizeOptions=s,r.prototype._bindTemplate(t),function(t,e,s,n){let r=s.hostProps||{};for(let e in n.instanceProps){delete r[e];let s=n.notifyInstanceProp;s&&t.prototype._addPropertyEffect(e,t.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:Ue(e,s)})}if(n.forwardHostProp&&e.__dataHost)for(let e in r)t.prototype._addPropertyEffect(e,t.prototype.PROPERTY_EFFECT_TYPES.NOTIFY,{fn:function(t,e,s){t.__dataHost._setPendingPropertyOrPath("_host_"+e,s[e],!0,!0)}})}(r,t,e,s),r}function Je(t,e,s){let n=s.forwardHostProp;if(n){let r=e.templatizeTemplateClass;if(!r){let t=s.mutableData?je:ze;r=e.templatizeTemplateClass=class extends t{};let i=e.hostProps;for(let t in i)r.prototype._addPropertyEffect("_host_"+t,r.prototype.PROPERTY_EFFECT_TYPES.PROPAGATE,{fn:Ve(t,n)}),r.prototype._createNotifyingProperty("_host_"+t)}!function(t,e){Fe=t,Object.setPrototypeOf(t,e.prototype),new e,Fe=null}(t,r),t.__dataProto&&Object.assign(t.__data,t.__dataProto),t.__dataTemp={},t.__dataPending=null,t.__dataOld=null,t._enableProperties()}}function Ve(t,e){return function(t,s,n){e.call(t.__templatizeOwner,s.substring("_host_".length),n[s])}}function Ue(t,e){return function(t,s,n){e.call(t.__templatizeOwner,t,s,n[s])}}function Xe(t,e,s){if(s=s||{},t.__templatizeOwner)throw new Error("A <template> can only be templatized once");t.__templatizeOwner=e;let n=(e?e.constructor:qe)._parseTemplate(t),r=n.templatizeInstanceClass;r||(r=Ye(t,n,s),n.templatizeInstanceClass=r),Je(t,n,s);let i=class extends r{};return i.prototype._methodHost=function(t){let e=t.__dataHost;return e&&e._methodHost||e}(t),i.prototype.__dataHost=t,i.prototype.__templatizeOwner=e,i.prototype.__hostProps=n.hostProps,i=i,i}function We(t,e){let s;for(;e;)if(s=e.__templatizeInstance){if(s.__dataHost==t)return s;e=s.__dataHost}else e=E(e).parentNode;return null}const Ge=function(){let t,e;do{t=window.ShadyDOM&&ShadyDOM.flush(),window.ShadyCSS&&window.ShadyCSS.ScopingShim&&window.ShadyCSS.ScopingShim.flush(),e=_()}while(t||e)};class Ze extends Re{static get is(){return"dom-if"}static get template(){return null}static get properties(){return{if:{type:Boolean,observer:"__debounceRender"},restamp:{type:Boolean,observer:"__debounceRender"}}}constructor(){super(),this.__renderDebouncer=null,this.__invalidProps=null,this.__instance=null,this._lastIf=!1,this.__ctor=null,this.__hideTemplateChildren__=!1}__debounceRender(){this.__renderDebouncer=c.debounce(this.__renderDebouncer,l,(()=>this.__render())),p(this.__renderDebouncer)}disconnectedCallback(){super.disconnectedCallback();const t=E(this).parentNode;t&&(t.nodeType!=Node.DOCUMENT_FRAGMENT_NODE||E(t).host)||this.__teardownInstance()}connectedCallback(){super.connectedCallback(),this.style.display="none",this.if&&this.__debounceRender()}render(){Ge()}__render(){if(this.if){if(!this.__ensureInstance())return;this._showHideChildren()}else this.restamp&&this.__teardownInstance();!this.restamp&&this.__instance&&this._showHideChildren(),this.if!=this._lastIf&&(this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0})),this._lastIf=this.if)}__ensureInstance(){let t=E(this).parentNode;if(t){if(!this.__ctor){let t=E(this).querySelector("template");if(!t){let t=new MutationObserver((()=>{if(!E(this).querySelector("template"))throw new Error("dom-if requires a <template> child");t.disconnect(),this.__render()}));return t.observe(this,{childList:!0}),!1}this.__ctor=Xe(t,this,{mutableData:!0,forwardHostProp:function(t,e){this.__instance&&(this.if?this.__instance.forwardHostProp(t,e):(this.__invalidProps=this.__invalidProps||Object.create(null),this.__invalidProps[wt(t)]=!0))}})}if(this.__instance){this.__syncHostProperties();let e=this.__instance.children;if(e&&e.length){if(E(this).previousSibling!==e[e.length-1])for(let s,n=0;n<e.length&&(s=e[n]);n++)E(t).insertBefore(s,this)}}else this.__instance=new this.__ctor,E(t).insertBefore(this.__instance.root,this)}return!0}__syncHostProperties(){let t=this.__invalidProps;if(t){for(let e in t)this.__instance._setPendingProperty(e,this.__dataHost[e]);this.__invalidProps=null,this.__instance._flushProperties()}}__teardownInstance(){if(this.__instance){let t=this.__instance.children;if(t&&t.length){let e=E(t[0]).parentNode;if(e){e=E(e);for(let s,n=0;n<t.length&&(s=t[n]);n++)e.removeChild(s)}}this.__instance=null,this.__invalidProps=null}}_showHideChildren(){let t=this.__hideTemplateChildren__||!this.if;this.__instance&&this.__instance._showHideChildren(t)}}customElements.define(Ze.is,Ze);const Ke=De(Re);class Qe extends Ke{static get is(){return"dom-repeat"}static get template(){return null}static get properties(){return{items:{type:Array},as:{type:String,value:"item"},indexAs:{type:String,value:"index"},itemsIndexAs:{type:String,value:"itemsIndex"},sort:{type:Function,observer:"__sortChanged"},filter:{type:Function,observer:"__filterChanged"},observe:{type:String,observer:"__observeChanged"},delay:Number,renderedItemCount:{type:Number,notify:!0,readOnly:!0},initialCount:{type:Number,observer:"__initializeChunking"},targetFramerate:{type:Number,value:20},_targetFrameTime:{type:Number,computed:"__computeFrameTime(targetFramerate)"}}}static get observers(){return["__itemsChanged(items.*)"]}constructor(){super(),this.__instances=[],this.__limit=1/0,this.__pool=[],this.__renderDebouncer=null,this.__itemsIdxToInstIdx={},this.__chunkCount=null,this.__lastChunkTime=null,this.__sortFn=null,this.__filterFn=null,this.__observePaths=null,this.__ctor=null,this.__isDetached=!0,this.template=null}disconnectedCallback(){super.disconnectedCallback(),this.__isDetached=!0;for(let t=0;t<this.__instances.length;t++)this.__detachInstance(t)}connectedCallback(){if(super.connectedCallback(),this.style.display="none",this.__isDetached){this.__isDetached=!1;let t=E(E(this).parentNode);for(let e=0;e<this.__instances.length;e++)this.__attachInstance(e,t)}}__ensureTemplatized(){if(!this.__ctor){let t=this.template=this.querySelector("template");if(!t){let t=new MutationObserver((()=>{if(!this.querySelector("template"))throw new Error("dom-repeat requires a <template> child");t.disconnect(),this.__render()}));return t.observe(this,{childList:!0}),!1}let e={};e[this.as]=!0,e[this.indexAs]=!0,e[this.itemsIndexAs]=!0,this.__ctor=Xe(t,this,{mutableData:this.mutableData,parentModel:!0,instanceProps:e,forwardHostProp:function(t,e){let s=this.__instances;for(let n,r=0;r<s.length&&(n=s[r]);r++)n.forwardHostProp(t,e)},notifyInstanceProp:function(t,e,s){if(Nt(this.as,e)){let n=t[this.itemsIndexAs];e==this.as&&(this.items[n]=s);let r=Ot(this.as,`${JSCompiler_renameProperty("items",this)}.${n}`,e);this.notifyPath(r,s)}}})}return!0}__getMethodHost(){return this.__dataHost._methodHost||this.__dataHost}__functionFromPropertyValue(t){if("string"==typeof t){let e=t,s=this.__getMethodHost();return function(){return s[e].apply(s,arguments)}}return t}__sortChanged(t){this.__sortFn=this.__functionFromPropertyValue(t),this.items&&this.__debounceRender(this.__render)}__filterChanged(t){this.__filterFn=this.__functionFromPropertyValue(t),this.items&&this.__debounceRender(this.__render)}__computeFrameTime(t){return Math.ceil(1e3/t)}__initializeChunking(){this.initialCount&&(this.__limit=this.initialCount,this.__chunkCount=this.initialCount,this.__lastChunkTime=performance.now())}__tryRenderChunk(){this.items&&this.__limit<this.items.length&&this.__debounceRender(this.__requestRenderChunk)}__requestRenderChunk(){requestAnimationFrame((()=>this.__renderChunk()))}__renderChunk(){let t=performance.now(),e=this._targetFrameTime/(t-this.__lastChunkTime);this.__chunkCount=Math.round(this.__chunkCount*e)||1,this.__limit+=this.__chunkCount,this.__lastChunkTime=t,this.__debounceRender(this.__render)}__observeChanged(){this.__observePaths=this.observe&&this.observe.replace(".*",".").split(" ")}__itemsChanged(t){this.items&&!Array.isArray(this.items)&&console.warn("dom-repeat expected array for `items`, found",this.items),this.__handleItemPath(t.path,t.value)||(this.__initializeChunking(),this.__debounceRender(this.__render))}__handleObservedPaths(t){if(this.__sortFn||this.__filterFn)if(t){if(this.__observePaths){let e=this.__observePaths;for(let s=0;s<e.length;s++)0===t.indexOf(e[s])&&this.__debounceRender(this.__render,this.delay)}}else this.__debounceRender(this.__render,this.delay)}__debounceRender(t,e=0){this.__renderDebouncer=c.debounce(this.__renderDebouncer,e>0?i.after(e):l,t.bind(this)),p(this.__renderDebouncer)}render(){this.__debounceRender(this.__render),Ge()}__render(){this.__ensureTemplatized()&&(this.__applyFullRefresh(),this.__pool.length=0,this._setRenderedItemCount(this.__instances.length),this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0})),this.__tryRenderChunk())}__applyFullRefresh(){let t=this.items||[],e=new Array(t.length);for(let s=0;s<t.length;s++)e[s]=s;this.__filterFn&&(e=e.filter(((e,s,n)=>this.__filterFn(t[e],s,n)))),this.__sortFn&&e.sort(((e,s)=>this.__sortFn(t[e],t[s])));const s=this.__itemsIdxToInstIdx={};let n=0;const r=Math.min(e.length,this.__limit);for(;n<r;n++){let r=this.__instances[n],i=e[n],o=t[i];s[i]=n,r?(r._setPendingProperty(this.as,o),r._setPendingProperty(this.indexAs,n),r._setPendingProperty(this.itemsIndexAs,i),r._flushProperties()):this.__insertInstance(o,n,i)}for(let t=this.__instances.length-1;t>=n;t--)this.__detachAndRemoveInstance(t)}__detachInstance(t){let e=this.__instances[t];const s=E(e.root);for(let t=0;t<e.children.length;t++){let n=e.children[t];s.appendChild(n)}return e}__attachInstance(t,e){let s=this.__instances[t];e.insertBefore(s.root,this)}__detachAndRemoveInstance(t){let e=this.__detachInstance(t);e&&this.__pool.push(e),this.__instances.splice(t,1)}__stampInstance(t,e,s){let n={};return n[this.as]=t,n[this.indexAs]=e,n[this.itemsIndexAs]=s,new this.__ctor(n)}__insertInstance(t,e,s){let n=this.__pool.pop();n?(n._setPendingProperty(this.as,t),n._setPendingProperty(this.indexAs,e),n._setPendingProperty(this.itemsIndexAs,s),n._flushProperties()):n=this.__stampInstance(t,e,s);let r=this.__instances[e+1],i=r?r.children[0]:this;return E(E(this).parentNode).insertBefore(n.root,i),this.__instances[e]=n,n}_showHideChildren(t){for(let e=0;e<this.__instances.length;e++)this.__instances[e]._showHideChildren(t)}__handleItemPath(t,e){let s=t.slice(6),n=s.indexOf("."),r=n<0?s:s.substring(0,n);if(r==parseInt(r,10)){let t=n<0?"":s.substring(n+1);this.__handleObservedPaths(t);let i=this.__itemsIdxToInstIdx[r],o=this.__instances[i];if(o){let s=this.as+(t?"."+t:"");o._setPendingPropertyOrPath(s,e,!1,!0),o._flushProperties()}return!0}}itemForElement(t){let e=this.modelForElement(t);return e&&e[this.as]}indexForElement(t){let e=this.modelForElement(t);return e&&e[this.indexAs]}modelForElement(t){return We(this.template,t)}}customElements.define(Qe.is,Qe);const ts=!(window.ShadyDOM&&window.ShadyDOM.inUse);let es,ss;function ns(t){es=(!t||!t.shimcssproperties)&&(ts||Boolean(!navigator.userAgent.match(/AppleWebKit\/601|Edge\/15/)&&window.CSS&&CSS.supports&&CSS.supports("box-shadow","0 0 0 var(--foo)")))}window.ShadyCSS&&void 0!==window.ShadyCSS.cssBuild&&(ss=window.ShadyCSS.cssBuild);const rs=Boolean(window.ShadyCSS&&window.ShadyCSS.disableRuntime);window.ShadyCSS&&void 0!==window.ShadyCSS.nativeCss?es=window.ShadyCSS.nativeCss:window.ShadyCSS?(ns(window.ShadyCSS),window.ShadyCSS=void 0):ns(window.WebComponents&&window.WebComponents.flags);const is=es;class os{constructor(){this.start=0,this.end=0,this.previous=null,this.parent=null,this.rules=null,this.parsedCssText="",this.cssText="",this.atRule=!1,this.type=0,this.keyframesName="",this.selector="",this.parsedSelector=""}}function as(t){return ls(function(t){let e=new os;e.start=0,e.end=t.length;let s=e;for(let n=0,r=t.length;n<r;n++)if(t[n]===cs){s.rules||(s.rules=[]);let t=s,e=t.rules[t.rules.length-1]||null;s=new os,s.start=n+1,s.parent=t,s.previous=e,t.rules.push(s)}else t[n]===us&&(s.end=n+1,s=s.parent||e);return e}(t=t.replace(ps.comments,"").replace(ps.port,"")),t)}function ls(t,e){let s=e.substring(t.start,t.end-1);if(t.parsedCssText=t.cssText=s.trim(),t.parent){let n=t.previous?t.previous.end:t.parent.start;s=e.substring(n,t.start-1),s=function(t){return t.replace(/\\([0-9a-f]{1,6})\s/gi,(function(){let t=arguments[1],e=6-t.length;for(;e--;)t="0"+t;return"\\"+t}))}(s),s=s.replace(ps.multipleSpaces," "),s=s.substring(s.lastIndexOf(";")+1);let r=t.parsedSelector=t.selector=s.trim();t.atRule=0===r.indexOf(ms),t.atRule?0===r.indexOf(fs)?t.type=ds.MEDIA_RULE:r.match(ps.keyframesRule)&&(t.type=ds.KEYFRAMES_RULE,t.keyframesName=t.selector.split(ps.multipleSpaces).pop()):0===r.indexOf(_s)?t.type=ds.MIXIN_RULE:t.type=ds.STYLE_RULE}let n=t.rules;if(n)for(let t,s=0,r=n.length;s<r&&(t=n[s]);s++)ls(t,e);return t}function hs(t,e,s=""){let n="";if(t.cssText||t.rules){let s=t.rules;if(s&&!function(t){let e=t[0];return Boolean(e)&&Boolean(e.selector)&&0===e.selector.indexOf(_s)}(s))for(let t,r=0,i=s.length;r<i&&(t=s[r]);r++)n=hs(t,e,n);else n=e?t.cssText:function(t){return function(t){return t.replace(ps.mixinApply,"").replace(ps.varApply,"")}(t=function(t){return t.replace(ps.customProp,"").replace(ps.mixinProp,"")}(t))}(t.cssText),n=n.trim(),n&&(n="  "+n+"\n")}return n&&(t.selector&&(s+=t.selector+" "+cs+"\n"),s+=n,t.selector&&(s+=us+"\n\n")),s}const ds={STYLE_RULE:1,KEYFRAMES_RULE:7,MEDIA_RULE:4,MIXIN_RULE:1e3},cs="{",us="}",ps={comments:/\/\*[^*]*\*+([^/*][^*]*\*+)*\//gim,port:/@import[^;]*;/gim,customProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?(?:[;\n]|$)/gim,mixinProp:/(?:^[^;\-\s}]+)?--[^;{}]*?:[^{};]*?{[^}]*?}(?:[;\n]|$)?/gim,mixinApply:/@apply\s*\(?[^);]*\)?\s*(?:[;\n]|$)?/gim,varApply:/[^;:]*?:[^;]*?var\([^;]*\)(?:[;\n]|$)?/gim,keyframesRule:/^@[^\s]*keyframes/,multipleSpaces:/\s+/g},_s="--",fs="@media",ms="@",ys=/(?:^|[;\s{]\s*)(--[\w-]*?)\s*:\s*(?:((?:'(?:\\'|.)*?'|"(?:\\"|.)*?"|\([^)]*?\)|[^};{])+)|\{([^}]*)\}(?:(?=[;\s}])|$))/gi,gs=/(?:^|\W+)@apply\s*\(?([^);\n]*)\)?/gi,bs=/@media\s(.*)/,Ps=new Set;function Cs(t){const e=t.textContent;if(!Ps.has(e)){Ps.add(e);const s=t.cloneNode(!0);document.head.appendChild(s)}}function vs(t){return t.hasAttribute("shady-unscoped")}function Ss(t,e){return t?("string"==typeof t&&(t=as(t)),e&&Es(t,e),hs(t,is)):""}function ws(t){return!t.__cssRules&&t.textContent&&(t.__cssRules=as(t.textContent)),t.__cssRules||null}function Es(t,e,s,n){if(!t)return;let r=!1,i=t.type;if(n&&i===ds.MEDIA_RULE){let e=t.selector.match(bs);e&&(window.matchMedia(e[1]).matches||(r=!0))}i===ds.STYLE_RULE?e(t):s&&i===ds.KEYFRAMES_RULE?s(t):i===ds.MIXIN_RULE&&(r=!0);let o=t.rules;if(o&&!r)for(let t,r=0,i=o.length;r<i&&(t=o[r]);r++)Es(t,e,s,n)}function Ts(t,e){let s=t.indexOf("var(");if(-1===s)return e(t,"","","");let n=function(t,e){let s=0;for(let n=e,r=t.length;n<r;n++)if("("===t[n])s++;else if(")"===t[n]&&0==--s)return n;return-1}(t,s+3),r=t.substring(s+4,n),i=t.substring(0,s),o=Ts(t.substring(n+1),e),a=r.indexOf(",");return-1===a?e(i,r.trim(),"",o):e(i,r.substring(0,a).trim(),r.substring(a+1).trim(),o)}window.ShadyDOM&&window.ShadyDOM.wrap;function Os(t){if(void 0!==ss)return ss;if(void 0===t.__cssBuild){const e=t.getAttribute("css-build");if(e)t.__cssBuild=e;else{const e=function(t){const e="template"===t.localName?t.content.firstChild:t.firstChild;if(e instanceof Comment){const t=e.textContent.trim().split(":");if("css-build"===t[0])return t[1]}return""}(t);""!==e&&function(t){const e="template"===t.localName?t.content.firstChild:t.firstChild;e.parentNode.removeChild(e)}(t),t.__cssBuild=e}}return t.__cssBuild||""}function Ns(t){return""!==Os(t)}function xs(t,e){for(let s in e)null===s?t.style.removeProperty(s):t.style.setProperty(s,e[s])}function As(t,e){const s=window.getComputedStyle(t).getPropertyValue(e);return s?s.trim():""}const Is=/;\s*/m,Ms=/^\s*(initial)|(inherit)\s*$/,Rs=/\s*!important/;class Ls{constructor(){this._map={}}set(t,e){t=t.trim(),this._map[t]={properties:e,dependants:{}}}get(t){return t=t.trim(),this._map[t]||null}}let ks=null;class Ds{constructor(){this._currentElement=null,this._measureElement=null,this._map=new Ls}detectMixin(t){return function(t){const e=gs.test(t)||ys.test(t);return gs.lastIndex=0,ys.lastIndex=0,e}(t)}gatherStyles(t){const e=function(t){const e=[],s=t.querySelectorAll("style");for(let t=0;t<s.length;t++){const n=s[t];vs(n)?ts||(Cs(n),n.parentNode.removeChild(n)):(e.push(n.textContent),n.parentNode.removeChild(n))}return e.join("").trim()}(t.content);if(e){const s=document.createElement("style");return s.textContent=e,t.content.insertBefore(s,t.content.firstChild),s}return null}transformTemplate(t,e){void 0===t._gatheredStyle&&(t._gatheredStyle=this.gatherStyles(t));const s=t._gatheredStyle;return s?this.transformStyle(s,e):null}transformStyle(t,e=""){let s=ws(t);return this.transformRules(s,e),t.textContent=Ss(s),s}transformCustomStyle(t){let e=ws(t);return Es(e,(t=>{":root"===t.selector&&(t.selector="html"),this.transformRule(t)})),t.textContent=Ss(e),e}transformRules(t,e){this._currentElement=e,Es(t,(t=>{this.transformRule(t)})),this._currentElement=null}transformRule(t){t.cssText=this.transformCssText(t.parsedCssText,t),":root"===t.selector&&(t.selector=":host > *")}transformCssText(t,e){return t=t.replace(ys,((t,s,n,r)=>this._produceCssProperties(t,s,n,r,e))),this._consumeCssProperties(t,e)}_getInitialValueForProperty(t){return this._measureElement||(this._measureElement=document.createElement("meta"),this._measureElement.setAttribute("apply-shim-measure",""),this._measureElement.style.all="initial",document.head.appendChild(this._measureElement)),window.getComputedStyle(this._measureElement).getPropertyValue(t)}_fallbacksFromPreviousRules(t){let e=t;for(;e.parent;)e=e.parent;const s={};let n=!1;return Es(e,(e=>{n=n||e===t,n||e.selector===t.selector&&Object.assign(s,this._cssTextToMap(e.parsedCssText))})),s}_consumeCssProperties(t,e){let s=null;for(;s=gs.exec(t);){let n=s[0],r=s[1],i=s.index,o=i+n.indexOf("@apply"),a=i+n.length,l=t.slice(0,o),h=t.slice(a),d=e?this._fallbacksFromPreviousRules(e):{};Object.assign(d,this._cssTextToMap(l));let c=this._atApplyToCssProperties(r,d);t=`${l}${c}${h}`,gs.lastIndex=i+c.length}return t}_atApplyToCssProperties(t,e){t=t.replace(Is,"");let s=[],n=this._map.get(t);if(n||(this._map.set(t,{}),n=this._map.get(t)),n){let r,i,o;this._currentElement&&(n.dependants[this._currentElement]=!0);const a=n.properties;for(r in a)o=e&&e[r],i=[r,": var(",t,"_-_",r],o&&i.push(",",o.replace(Rs,"")),i.push(")"),Rs.test(a[r])&&i.push(" !important"),s.push(i.join(""))}return s.join("; ")}_replaceInitialOrInherit(t,e){let s=Ms.exec(e);return s&&(e=s[1]?this._getInitialValueForProperty(t):"apply-shim-inherit"),e}_cssTextToMap(t,e=!1){let s,n,r=t.split(";"),i={};for(let t,o,a=0;a<r.length;a++)t=r[a],t&&(o=t.split(":"),o.length>1&&(s=o[0].trim(),n=o.slice(1).join(":"),e&&(n=this._replaceInitialOrInherit(s,n)),i[s]=n));return i}_invalidateMixinEntry(t){if(ks)for(let e in t.dependants)e!==this._currentElement&&ks(e)}_produceCssProperties(t,e,s,n,r){if(s&&Ts(s,((t,e)=>{e&&this._map.get(e)&&(n=`@apply ${e};`)})),!n)return t;let i=this._consumeCssProperties(""+n,r),o=t.slice(0,t.indexOf("--")),a=this._cssTextToMap(i,!0),l=a,h=this._map.get(e),d=h&&h.properties;d?l=Object.assign(Object.create(d),a):this._map.set(e,l);let c,u,p=[],_=!1;for(c in l)u=a[c],void 0===u&&(u="initial"),d&&!(c in d)&&(_=!0),p.push(`${e}_-_${c}: ${u}`);return _&&this._invalidateMixinEntry(h),h&&(h.properties=l),s&&(o=`${t};${o}`),`${o}${p.join("; ")};`}}Ds.prototype.detectMixin=Ds.prototype.detectMixin,Ds.prototype.transformStyle=Ds.prototype.transformStyle,Ds.prototype.transformCustomStyle=Ds.prototype.transformCustomStyle,Ds.prototype.transformRules=Ds.prototype.transformRules,Ds.prototype.transformRule=Ds.prototype.transformRule,Ds.prototype.transformTemplate=Ds.prototype.transformTemplate,Ds.prototype._separator="_-_",Object.defineProperty(Ds.prototype,"invalidCallback",{get:()=>ks,set(t){ks=t}});const Fs={},Hs="_applyShimCurrentVersion",zs="_applyShimNextVersion",js="_applyShimValidatingVersion",Bs=Promise.resolve();function qs(t){let e=Fs[t];e&&function(t){t[Hs]=t[Hs]||0,t[js]=t[js]||0,t[zs]=(t[zs]||0)+1}(e)}function $s(t){return t[Hs]===t[zs]}let Ys,Js=null,Vs=window.HTMLImports&&window.HTMLImports.whenReady||null;function Us(t){requestAnimationFrame((function(){Vs?Vs(t):(Js||(Js=new Promise((t=>{Ys=t})),"complete"===document.readyState?Ys():document.addEventListener("readystatechange",(()=>{"complete"===document.readyState&&Ys()}))),Js.then((function(){t&&t()})))}))}const Xs="__shadyCSSCachedStyle";let Ws=null,Gs=null;class Zs{constructor(){this.customStyles=[],this.enqueued=!1,Us((()=>{window.ShadyCSS.flushCustomStyles&&window.ShadyCSS.flushCustomStyles()}))}enqueueDocumentValidation(){!this.enqueued&&Gs&&(this.enqueued=!0,Us(Gs))}addCustomStyle(t){t.__seenByShadyCSS||(t.__seenByShadyCSS=!0,this.customStyles.push(t),this.enqueueDocumentValidation())}getStyleForCustomStyle(t){if(t[Xs])return t[Xs];let e;return e=t.getStyle?t.getStyle():t,e}processStyles(){const t=this.customStyles;for(let e=0;e<t.length;e++){const s=t[e];if(s[Xs])continue;const n=this.getStyleForCustomStyle(s);if(n){const t=n.__appliedElement||n;Ws&&Ws(t),s[Xs]=t}}return t}}Zs.prototype.addCustomStyle=Zs.prototype.addCustomStyle,Zs.prototype.getStyleForCustomStyle=Zs.prototype.getStyleForCustomStyle,Zs.prototype.processStyles=Zs.prototype.processStyles,Object.defineProperties(Zs.prototype,{transformCallback:{get:()=>Ws,set(t){Ws=t}},validateCallback:{get:()=>Gs,set(t){let e=!1;Gs||(e=!0),Gs=t,e&&this.enqueueDocumentValidation()}}});const Ks=new Ds;class Qs{constructor(){this.customStyleInterface=null,Ks.invalidCallback=qs}ensure(){this.customStyleInterface||window.ShadyCSS.CustomStyleInterface&&(this.customStyleInterface=window.ShadyCSS.CustomStyleInterface,this.customStyleInterface.transformCallback=t=>{Ks.transformCustomStyle(t)},this.customStyleInterface.validateCallback=()=>{requestAnimationFrame((()=>{this.customStyleInterface.enqueued&&this.flushCustomStyles()}))})}prepareTemplate(t,e){if(this.ensure(),Ns(t))return;Fs[e]=t;let s=Ks.transformTemplate(t,e);t._styleAst=s}flushCustomStyles(){if(this.ensure(),!this.customStyleInterface)return;let t=this.customStyleInterface.processStyles();if(this.customStyleInterface.enqueued){for(let e=0;e<t.length;e++){let s=t[e],n=this.customStyleInterface.getStyleForCustomStyle(s);n&&Ks.transformCustomStyle(n)}this.customStyleInterface.enqueued=!1}}styleSubtree(t,e){if(this.ensure(),e&&xs(t,e),t.shadowRoot){this.styleElement(t);let e=t.shadowRoot.children||t.shadowRoot.childNodes;for(let t=0;t<e.length;t++)this.styleSubtree(e[t])}else{let e=t.children||t.childNodes;for(let t=0;t<e.length;t++)this.styleSubtree(e[t])}}styleElement(t){this.ensure();let{is:e}=function(t){let e=t.localName,s="",n="";return e?e.indexOf("-")>-1?s=e:(n=e,s=t.getAttribute&&t.getAttribute("is")||""):(s=t.is,n=t.extends),{is:s,typeExtension:n}}(t),s=Fs[e];if((!s||!Ns(s))&&s&&!$s(s)){(function(t){return!$s(t)&&t[js]===t[zs]})(s)||(this.prepareTemplate(s,e),function(t){t[js]=t[zs],t._validating||(t._validating=!0,Bs.then((function(){t[Hs]=t[zs],t._validating=!1})))}(s));let n=t.shadowRoot;if(n){let t=n.querySelector("style");t&&(t.__cssRules=s._styleAst,t.textContent=Ss(s._styleAst))}}}styleDocument(t){this.ensure(),this.styleSubtree(document.body,t)}}if(!window.ShadyCSS||!window.ShadyCSS.ScopingShim){const t=new Qs;let e=window.ShadyCSS&&window.ShadyCSS.CustomStyleInterface;window.ShadyCSS={prepareTemplate(e,s,n){t.flushCustomStyles(),t.prepareTemplate(e,s)},prepareTemplateStyles(t,e,s){window.ShadyCSS.prepareTemplate(t,e,s)},prepareTemplateDom(t,e){},styleSubtree(e,s){t.flushCustomStyles(),t.styleSubtree(e,s)},styleElement(e){t.flushCustomStyles(),t.styleElement(e)},styleDocument(e){t.flushCustomStyles(),t.styleDocument(e)},getComputedStyleValue:(t,e)=>As(t,e),flushCustomStyles(){t.flushCustomStyles()},nativeCss:is,nativeShadow:ts,cssBuild:ss,disableRuntime:rs},e&&(window.ShadyCSS.CustomStyleInterface=e)}window.ShadyCSS.ApplyShim=Ks;const tn=d((t=>class extends t{_addEventListenerToNode(t,e,s){Q(t,e,s)||super._addEventListenerToNode(t,e,s)}_removeEventListenerFromNode(t,e,s){tt(t,e,s)||super._removeEventListenerFromNode(t,e,s)}}));let en=!1,sn=[],nn=[];function rn(){en=!0,requestAnimationFrame((function(){en=!1,function(t){for(;t.length;)on(t.shift())}(sn),setTimeout((function(){!function(t){for(let e=0,s=t.length;e<s;e++)on(t.shift())}(nn)}))}))}function on(t){const e=t[0],s=t[1],n=t[2];try{s.apply(e,n)}catch(t){setTimeout((()=>{throw t}))}}function an(t,e,s){en||rn(),sn.push([t,e,s])}function ln(t,e,s){en||rn(),nn.push([t,e,s])}function hn(){document.body.removeAttribute("unresolved")}function dn(t,e,s){return{index:t,removed:e,addedCount:s}}"interactive"===document.readyState||"complete"===document.readyState?hn():window.addEventListener("DOMContentLoaded",hn);function cn(t,e,s,n,r,i){let o,a=0,l=0,h=Math.min(s-e,i-r);if(0==e&&0==r&&(a=function(t,e,s){for(let n=0;n<s;n++)if(!pn(t[n],e[n]))return n;return s}(t,n,h)),s==t.length&&i==n.length&&(l=function(t,e,s){let n=t.length,r=e.length,i=0;for(;i<s&&pn(t[--n],e[--r]);)i++;return i}(t,n,h-a)),r+=a,i-=l,(s-=l)-(e+=a)==0&&i-r==0)return[];if(e==s){for(o=dn(e,[],0);r<i;)o.removed.push(n[r++]);return[o]}if(r==i)return[dn(e,[],s-e)];let d=function(t){let e=t.length-1,s=t[0].length-1,n=t[e][s],r=[];for(;e>0||s>0;){if(0==e){r.push(2),s--;continue}if(0==s){r.push(3),e--;continue}let i,o=t[e-1][s-1],a=t[e-1][s],l=t[e][s-1];i=a<l?a<o?a:o:l<o?l:o,i==o?(o==n?r.push(0):(r.push(1),n=o),e--,s--):i==a?(r.push(3),e--,n=a):(r.push(2),s--,n=l)}return r.reverse(),r}(function(t,e,s,n,r,i){let o=i-r+1,a=s-e+1,l=new Array(o);for(let t=0;t<o;t++)l[t]=new Array(a),l[t][0]=t;for(let t=0;t<a;t++)l[0][t]=t;for(let s=1;s<o;s++)for(let i=1;i<a;i++)if(pn(t[e+i-1],n[r+s-1]))l[s][i]=l[s-1][i-1];else{let t=l[s-1][i]+1,e=l[s][i-1]+1;l[s][i]=t<e?t:e}return l}(t,e,s,n,r,i));o=void 0;let c=[],u=e,p=r;for(let t=0;t<d.length;t++)switch(d[t]){case 0:o&&(c.push(o),o=void 0),u++,p++;break;case 1:o||(o=dn(u,[],0)),o.addedCount++,u++,o.removed.push(n[p]),p++;break;case 2:o||(o=dn(u,[],0)),o.addedCount++,u++;break;case 3:o||(o=dn(u,[],0)),o.removed.push(n[p]),p++}return o&&c.push(o),c}function un(t,e){return cn(t,0,t.length,e,0,e.length)}function pn(t,e){return t===e}function _n(t){return"slot"===t.localName}let fn=class{static getFlattenedNodes(t){const e=E(t);return _n(t)?(t=t,e.assignedNodes({flatten:!0})):Array.from(e.childNodes).map((t=>_n(t)?E(t=t).assignedNodes({flatten:!0}):[t])).reduce(((t,e)=>t.concat(e)),[])}constructor(t,e){this._shadyChildrenObserver=null,this._nativeChildrenObserver=null,this._connected=!1,this._target=t,this.callback=e,this._effectiveNodes=[],this._observer=null,this._scheduled=!1,this._boundSchedule=()=>{this._schedule()},this.connect(),this._schedule()}connect(){_n(this._target)?this._listenSlots([this._target]):E(this._target).children&&(this._listenSlots(E(this._target).children),window.ShadyDOM?this._shadyChildrenObserver=ShadyDOM.observeChildren(this._target,(t=>{this._processMutations(t)})):(this._nativeChildrenObserver=new MutationObserver((t=>{this._processMutations(t)})),this._nativeChildrenObserver.observe(this._target,{childList:!0}))),this._connected=!0}disconnect(){_n(this._target)?this._unlistenSlots([this._target]):E(this._target).children&&(this._unlistenSlots(E(this._target).children),window.ShadyDOM&&this._shadyChildrenObserver?(ShadyDOM.unobserveChildren(this._shadyChildrenObserver),this._shadyChildrenObserver=null):this._nativeChildrenObserver&&(this._nativeChildrenObserver.disconnect(),this._nativeChildrenObserver=null)),this._connected=!1}_schedule(){this._scheduled||(this._scheduled=!0,l.run((()=>this.flush())))}_processMutations(t){this._processSlotMutations(t),this.flush()}_processSlotMutations(t){if(t)for(let e=0;e<t.length;e++){let s=t[e];s.addedNodes&&this._listenSlots(s.addedNodes),s.removedNodes&&this._unlistenSlots(s.removedNodes)}}flush(){if(!this._connected)return!1;window.ShadyDOM&&ShadyDOM.flush(),this._nativeChildrenObserver?this._processSlotMutations(this._nativeChildrenObserver.takeRecords()):this._shadyChildrenObserver&&this._processSlotMutations(this._shadyChildrenObserver.takeRecords()),this._scheduled=!1;let t={target:this._target,addedNodes:[],removedNodes:[]},e=this.constructor.getFlattenedNodes(this._target),s=un(e,this._effectiveNodes);for(let e,n=0;n<s.length&&(e=s[n]);n++)for(let s,n=0;n<e.removed.length&&(s=e.removed[n]);n++)t.removedNodes.push(s);for(let n,r=0;r<s.length&&(n=s[r]);r++)for(let s=n.index;s<n.index+n.addedCount;s++)t.addedNodes.push(e[s]);this._effectiveNodes=e;let n=!1;return(t.addedNodes.length||t.removedNodes.length)&&(n=!0,this.callback.call(this._target,t)),n}_listenSlots(t){for(let e=0;e<t.length;e++){let s=t[e];_n(s)&&s.addEventListener("slotchange",this._boundSchedule)}}_unlistenSlots(t){for(let e=0;e<t.length;e++){let s=t[e];_n(s)&&s.removeEventListener("slotchange",this._boundSchedule)}}};const mn=Element.prototype,yn=mn.matches||mn.matchesSelector||mn.mozMatchesSelector||mn.msMatchesSelector||mn.oMatchesSelector||mn.webkitMatchesSelector,gn=function(t,e){return yn.call(t,e)};class bn{constructor(t){this.node=t}observeNodes(t){return new fn(this.node,t)}unobserveNodes(t){t.disconnect()}notifyObserver(){}deepContains(t){if(E(this.node).contains(t))return!0;let e=t,s=t.ownerDocument;for(;e&&e!==s&&e!==this.node;)e=E(e).parentNode||E(e).host;return e===this.node}getOwnerRoot(){return E(this.node).getRootNode()}getDistributedNodes(){return"slot"===this.node.localName?E(this.node).assignedNodes({flatten:!0}):[]}getDestinationInsertionPoints(){let t=[],e=E(this.node).assignedSlot;for(;e;)t.push(e),e=E(e).assignedSlot;return t}importNode(t,e){let s=this.node instanceof Document?this.node:this.node.ownerDocument;return E(s).importNode(t,e)}getEffectiveChildNodes(){return fn.getFlattenedNodes(this.node)}queryDistributedElements(t){let e=this.getEffectiveChildNodes(),s=[];for(let n,r=0,i=e.length;r<i&&(n=e[r]);r++)n.nodeType===Node.ELEMENT_NODE&&gn(n,t)&&s.push(n);return s}get activeElement(){let t=this.node;return void 0!==t._activeElement?t._activeElement:t.activeElement}}function Pn(t,e){for(let s=0;s<e.length;s++){let n=e[s];Object.defineProperty(t,n,{get:function(){return this.node[n]},configurable:!0})}}class Cn{constructor(t){this.event=t}get rootTarget(){return this.path[0]}get localTarget(){return this.event.target}get path(){return this.event.composedPath()}}bn.prototype.cloneNode,bn.prototype.appendChild,bn.prototype.insertBefore,bn.prototype.removeChild,bn.prototype.replaceChild,bn.prototype.setAttribute,bn.prototype.removeAttribute,bn.prototype.querySelector,bn.prototype.querySelectorAll,bn.prototype.parentNode,bn.prototype.firstChild,bn.prototype.lastChild,bn.prototype.nextSibling,bn.prototype.previousSibling,bn.prototype.firstElementChild,bn.prototype.lastElementChild,bn.prototype.nextElementSibling,bn.prototype.previousElementSibling,bn.prototype.childNodes,bn.prototype.children,bn.prototype.classList,bn.prototype.textContent,bn.prototype.innerHTML;let vn=bn;if(window.ShadyDOM&&window.ShadyDOM.inUse&&window.ShadyDOM.noPatch&&window.ShadyDOM.Wrapper){class t extends window.ShadyDOM.Wrapper{}Object.getOwnPropertyNames(bn.prototype).forEach((e=>{"activeElement"!=e&&(t.prototype[e]=bn.prototype[e])})),Pn(t.prototype,["classList"]),vn=t,Object.defineProperties(Cn.prototype,{localTarget:{get(){return this.event.currentTarget},configurable:!0},path:{get(){return window.ShadyDOM.composedPath(this.event)},configurable:!0}})}else!function(t,e){for(let s=0;s<e.length;s++){let n=e[s];t[n]=function(){return this.node[n].apply(this.node,arguments)}}}(bn.prototype,["cloneNode","appendChild","insertBefore","removeChild","replaceChild","setAttribute","removeAttribute","querySelector","querySelectorAll"]),Pn(bn.prototype,["parentNode","firstChild","lastChild","nextSibling","previousSibling","firstElementChild","lastElementChild","nextElementSibling","previousElementSibling","childNodes","children","classList"]),function(t,e){for(let s=0;s<e.length;s++){let n=e[s];Object.defineProperty(t,n,{get:function(){return this.node[n]},set:function(t){this.node[n]=t},configurable:!0})}}(bn.prototype,["textContent","innerHTML"]);const Sn=function(t){if((t=t||document)instanceof vn)return t;if(t instanceof Cn)return t;let e=t.__domApi;return e||(e=t instanceof Event?new Cn(t):new vn(t),t.__domApi=e),e};let wn=window.ShadyCSS;const En=d((t=>{const e=tn(xe(t)),s={x:"pan-x",y:"pan-y",none:"none",all:"auto"};class n extends e{constructor(){super(),this.isAttached,this.__boundListeners,this._debouncers}static get importMeta(){return this.prototype.importMeta}created(){}connectedCallback(){super.connectedCallback(),this.isAttached=!0,this.attached()}attached(){}disconnectedCallback(){super.disconnectedCallback(),this.isAttached=!1,this.detached()}detached(){}attributeChangedCallback(t,e,s,n){e!==s&&(super.attributeChangedCallback(t,e,s,n),this.attributeChanged(t,e,s))}attributeChanged(t,e,s){}_initializeProperties(){let t=Object.getPrototypeOf(this);t.hasOwnProperty("__hasRegisterFinished")||(this._registered(),t.__hasRegisterFinished=!0),super._initializeProperties(),this.root=this,this.created(),this._applyListeners()}_registered(){}ready(){this._ensureAttributes(),super.ready()}_ensureAttributes(){}_applyListeners(){}serialize(t){return this._serializeValue(t)}deserialize(t,e){return this._deserializeValue(t,e)}reflectPropertyToAttribute(t,e,s){this._propertyToAttribute(t,e,s)}serializeValueToAttribute(t,e,s){this._valueToNodeAttribute(s||this,t,e)}extend(t,e){if(!t||!e)return t||e;let s=Object.getOwnPropertyNames(e);for(let n,r=0;r<s.length&&(n=s[r]);r++){let s=Object.getOwnPropertyDescriptor(e,n);s&&Object.defineProperty(t,n,s)}return t}mixin(t,e){for(let s in e)t[s]=e[s];return t}chainObject(t,e){return t&&e&&t!==e&&(t.__proto__=e),t}instanceTemplate(t){let e=this.constructor._contentForTemplate(t);return document.importNode(e,!0)}fire(t,e,s){s=s||{},e=null==e?{}:e;let n=new Event(t,{bubbles:void 0===s.bubbles||s.bubbles,cancelable:Boolean(s.cancelable),composed:void 0===s.composed||s.composed});n.detail=e;let r=s.node||this;return E(r).dispatchEvent(n),n}listen(t,e,s){t=t||this;let n=this.__boundListeners||(this.__boundListeners=new WeakMap),r=n.get(t);r||(r={},n.set(t,r));let i=e+s;r[i]||(r[i]=this._addMethodEventListenerToNode(t,e,s,this))}unlisten(t,e,s){t=t||this;let n=this.__boundListeners&&this.__boundListeners.get(t),r=e+s,i=n&&n[r];i&&(this._removeEventListenerFromNode(t,e,i),n[r]=null)}setScrollDirection(t,e){st(e||this,s[t]||"auto")}$$(t){return this.root.querySelector(t)}get domHost(){let t=E(this).getRootNode();return t instanceof DocumentFragment?t.host:t}distributeContent(){const t=Sn(this);window.ShadyDOM&&t.shadowRoot&&ShadyDOM.flush()}getEffectiveChildNodes(){return Sn(this).getEffectiveChildNodes()}queryDistributedElements(t){return Sn(this).queryDistributedElements(t)}getEffectiveChildren(){return this.getEffectiveChildNodes().filter((function(t){return t.nodeType===Node.ELEMENT_NODE}))}getEffectiveTextContent(){let t=this.getEffectiveChildNodes(),e=[];for(let s,n=0;s=t[n];n++)s.nodeType!==Node.COMMENT_NODE&&e.push(s.textContent);return e.join("")}queryEffectiveChildren(t){let e=this.queryDistributedElements(t);return e&&e[0]}queryAllEffectiveChildren(t){return this.queryDistributedElements(t)}getContentChildNodes(t){let e=this.root.querySelector(t||"slot");return e?Sn(e).getDistributedNodes():[]}getContentChildren(t){return this.getContentChildNodes(t).filter((function(t){return t.nodeType===Node.ELEMENT_NODE}))}isLightDescendant(t){const e=this;return e!==t&&E(e).contains(t)&&E(e).getRootNode()===E(t).getRootNode()}isLocalDescendant(t){return this.root===E(t).getRootNode()}scopeSubtree(t,e){}getComputedStyleValue(t){return wn.getComputedStyleValue(this,t)}debounce(t,e,s){return this._debouncers=this._debouncers||{},this._debouncers[t]=c.debounce(this._debouncers[t],s>0?i.after(s):l,e.bind(this))}isDebouncerActive(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];return!(!e||!e.isActive())}flushDebouncer(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];e&&e.flush()}cancelDebouncer(t){this._debouncers=this._debouncers||{};let e=this._debouncers[t];e&&e.cancel()}async(t,e){return e>0?i.run(t.bind(this),e):~l.run(t.bind(this))}cancelAsync(t){t<0?l.cancel(~t):i.cancel(t)}create(t,e){let s=document.createElement(t);if(e)if(s.setProperties)s.setProperties(e);else for(let t in e)s[t]=e[t];return s}elementMatches(t,e){return gn(e||this,t)}toggleAttribute(t,e){let s=this;return 3===arguments.length&&(s=arguments[2]),1==arguments.length&&(e=!s.hasAttribute(t)),e?(E(s).setAttribute(t,""),!0):(E(s).removeAttribute(t),!1)}toggleClass(t,e,s){s=s||this,1==arguments.length&&(e=!s.classList.contains(t)),e?s.classList.add(t):s.classList.remove(t)}transform(t,e){(e=e||this).style.webkitTransform=t,e.style.transform=t}translate3d(t,e,s,n){n=n||this,this.transform("translate3d("+t+","+e+","+s+")",n)}arrayDelete(t,e){let s;if(Array.isArray(t)){if(s=t.indexOf(e),s>=0)return t.splice(s,1)}else{if(s=It(this,t).indexOf(e),s>=0)return this.splice(t,s,1)}return null}_logger(t,e){switch(Array.isArray(e)&&1===e.length&&Array.isArray(e[0])&&(e=e[0]),t){case"log":case"warn":case"error":console[t](...e)}}_log(...t){this._logger("log",t)}_warn(...t){this._logger("warn",t)}_error(...t){this._logger("error",t)}_logf(t,...e){return["[%s::%s]",this.is,t,...e]}}return n.prototype.is="",n})),Tn={attached:!0,detached:!0,ready:!0,created:!0,beforeRegister:!0,registered:!0,attributeChanged:!0,listeners:!0,hostAttributes:!0},On={attached:!0,detached:!0,ready:!0,created:!0,beforeRegister:!0,registered:!0,attributeChanged:!0,behaviors:!0,_noAccessors:!0},Nn=Object.assign({listeners:!0,hostAttributes:!0,properties:!0,observers:!0},On);function xn(t,e){return Rn({},En(e),t)}function An(t,e,s,n){!function(t,e,s){const n=t._noAccessors,r=Object.getOwnPropertyNames(t);for(let i=0;i<r.length;i++){let o=r[i];if(!(o in s))if(n)e[o]=t[o];else{let s=Object.getOwnPropertyDescriptor(t,o);s&&(s.configurable=!0,Object.defineProperty(e,o,s))}}}(e,t,n);for(let t in Tn)e[t]&&(s[t]=s[t]||[],s[t].push(e[t]))}function In(t,e,s){e=e||[];for(let n=t.length-1;n>=0;n--){let r=t[n];r?Array.isArray(r)?In(r,e):e.indexOf(r)<0&&(!s||s.indexOf(r)<0)&&e.unshift(r):console.warn("behavior is null, check for missing or 404 import")}return e}function Mn(t,e){for(const s in e){const n=t[s],r=e[s];t[s]=!("value"in r)&&n&&"value"in n?Object.assign({value:n.value},r):r}}function Rn(t,e,s){let n;const r={};class i extends e{static _finalizeClass(){if(this.hasOwnProperty(JSCompiler_renameProperty("generatedFrom",this))){if(n)for(let t,e=0;e<n.length;e++)t=n[e],t.properties&&this.createProperties(t.properties),t.observers&&this.createObservers(t.observers,t.properties);t.properties&&this.createProperties(t.properties),t.observers&&this.createObservers(t.observers,t.properties),this._prepareTemplate()}else super._finalizeClass()}static get properties(){const e={};if(n)for(let t=0;t<n.length;t++)Mn(e,n[t].properties);return Mn(e,t.properties),e}static get observers(){let e=[];if(n)for(let t,s=0;s<n.length;s++)t=n[s],t.observers&&(e=e.concat(t.observers));return t.observers&&(e=e.concat(t.observers)),e}created(){super.created();const t=r.created;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}_registered(){const t=i.prototype;if(!t.hasOwnProperty("__hasRegisterFinished")){t.__hasRegisterFinished=!0,super._registered();const e=Object.getPrototypeOf(this);let s=r.beforeRegister;if(s)for(let t=0;t<s.length;t++)s[t].call(e);if(s=r.registered,s)for(let t=0;t<s.length;t++)s[t].call(e)}}_applyListeners(){super._applyListeners();const t=r.listeners;if(t)for(let e=0;e<t.length;e++){const s=t[e];if(s)for(let t in s)this._addMethodEventListenerToNode(this,t,s[t])}}_ensureAttributes(){const t=r.hostAttributes;if(t)for(let e=t.length-1;e>=0;e--){const s=t[e];for(let t in s)this._ensureAttribute(t,s[t])}super._ensureAttributes()}ready(){super.ready();let t=r.ready;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}attached(){super.attached();let t=r.attached;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}detached(){super.detached();let t=r.detached;if(t)for(let e=0;e<t.length;e++)t[e].call(this)}attributeChanged(t,e,s){super.attributeChanged();let n=r.attributeChanged;if(n)for(let r=0;r<n.length;r++)n[r].call(this,t,e,s)}}if(s){Array.isArray(s)||(s=[s]);let t=e.prototype.behaviors;n=In(s,null,t),i.prototype.behaviors=t?t.concat(s):n}return(e=>{n&&function(t,e,s){for(let n=0;n<e.length;n++)An(t,e[n],s,Nn)}(e,n,r),An(e,t,r,On)})(i.prototype),i.generatedFrom=t,i}let Ln;Ln=ke._mutablePropertyChange;const kn={properties:{mutableData:Boolean},_shouldPropertyChange(t,e,s){return Ln(this,t,e,s,this.mutableData)}},Dn=function(t){let e;return e="function"==typeof t?t:Dn.Class(t),customElements.define(e.is,e),e};Dn.Class=function(t,e){t||console.warn("Polymer.Class requires `info` argument");let s=e?e(En(HTMLElement)):En(HTMLElement);return s=Rn(t,s,t.behaviors),s.is=s.prototype.is=t.is,s};const Fn={templatize(t,e){this._templatizerTemplate=t,this.ctor=Xe(t,this,{mutableData:Boolean(e),parentModel:this._parentModel,instanceProps:this._instanceProps,forwardHostProp:this._forwardHostPropV2,notifyInstanceProp:this._notifyInstancePropV2})},stamp(t){return new this.ctor(t)},modelForElement(t){return We(this._templatizerTemplate,t)}},Hn=tn(De(Ee(HTMLElement)));customElements.define("dom-bind",class extends Hn{static get observedAttributes(){return["mutable-data"]}constructor(){super(),this.root=null,this.$=null,this.__children=null}attributeChangedCallback(){this.mutableData=!0}connectedCallback(){this.style.display="none",this.render()}disconnectedCallback(){this.__removeChildren()}__insertChildren(){E(E(this).parentNode).insertBefore(this.root,this)}__removeChildren(){if(this.__children)for(let t=0;t<this.__children.length;t++)this.root.appendChild(this.__children[t])}render(){let t;if(!this.__children){if(t=t||this.querySelector("template"),!t){let e=new MutationObserver((()=>{if(t=this.querySelector("template"),!t)throw new Error("dom-bind requires a <template> child");e.disconnect(),this.render()}));return void e.observe(this,{childList:!0})}this.root=this._stampTemplate(t),this.$=this.root.$,this.__children=[];for(let t=this.root.firstChild;t;t=t.nextSibling)this.__children[this.__children.length]=t;this._enableProperties()}this.__insertChildren(),this.dispatchEvent(new CustomEvent("dom-change",{bubbles:!0,composed:!0}))}});let zn=d((t=>{let e=xe(t);return class extends e{static get properties(){return{items:{type:Array},multi:{type:Boolean,value:!1},selected:{type:Object,notify:!0},selectedItem:{type:Object,notify:!0},toggle:{type:Boolean,value:!1}}}static get observers(){return["__updateSelection(multi, items.*)"]}constructor(){super(),this.__lastItems=null,this.__lastMulti=null,this.__selectedMap=null}__updateSelection(t,e){let s=e.path;if(s==JSCompiler_renameProperty("items",this)){let s=e.base||[],n=this.__lastItems;if(t!==this.__lastMulti&&this.clearSelection(),n){let t=un(s,n);this.__applySplices(t)}this.__lastItems=s,this.__lastMulti=t}else if(e.path==JSCompiler_renameProperty("items",this)+".splices")this.__applySplices(e.value.indexSplices);else{let t=s.slice((JSCompiler_renameProperty("items",this)+".").length),e=parseInt(t,10);t.indexOf(".")<0&&t==e&&this.__deselectChangedIdx(e)}}__applySplices(t){let e=this.__selectedMap;for(let s=0;s<t.length;s++){let n=t[s];e.forEach(((t,s)=>{t<n.index||(t>=n.index+n.removed.length?e.set(s,t+n.addedCount-n.removed.length):e.set(s,-1))}));for(let t=0;t<n.addedCount;t++){let s=n.index+t;e.has(this.items[s])&&e.set(this.items[s],s)}}this.__updateLinks();let s=0;e.forEach(((t,n)=>{t<0?(this.multi?this.splice(JSCompiler_renameProperty("selected",this),s,1):this.selected=this.selectedItem=null,e.delete(n)):s++}))}__updateLinks(){if(this.__dataLinkedPaths={},this.multi){let t=0;this.__selectedMap.forEach((e=>{e>=0&&this.linkPaths(`${JSCompiler_renameProperty("items",this)}.${e}`,`${JSCompiler_renameProperty("selected",this)}.${t++}`)}))}else this.__selectedMap.forEach((t=>{this.linkPaths(JSCompiler_renameProperty("selected",this),`${JSCompiler_renameProperty("items",this)}.${t}`),this.linkPaths(JSCompiler_renameProperty("selectedItem",this),`${JSCompiler_renameProperty("items",this)}.${t}`)}))}clearSelection(){this.__dataLinkedPaths={},this.__selectedMap=new Map,this.selected=this.multi?[]:null,this.selectedItem=null}isSelected(t){return this.__selectedMap.has(t)}isIndexSelected(t){return this.isSelected(this.items[t])}__deselectChangedIdx(t){let e=this.__selectedIndexForItemIndex(t);if(e>=0){let t=0;this.__selectedMap.forEach(((s,n)=>{e==t++&&this.deselect(n)}))}}__selectedIndexForItemIndex(t){let e=this.__dataLinkedPaths[`${JSCompiler_renameProperty("items",this)}.${t}`];if(e)return parseInt(e.slice((JSCompiler_renameProperty("selected",this)+".").length),10)}deselect(t){let e=this.__selectedMap.get(t);if(e>=0){let s;this.__selectedMap.delete(t),this.multi&&(s=this.__selectedIndexForItemIndex(e)),this.__updateLinks(),this.multi?this.splice(JSCompiler_renameProperty("selected",this),s,1):this.selected=this.selectedItem=null}}deselectIndex(t){this.deselect(this.items[t])}select(t){this.selectIndex(this.items.indexOf(t))}selectIndex(t){let e=this.items[t];this.isSelected(e)?this.toggle&&this.deselectIndex(t):(this.multi||this.__selectedMap.clear(),this.__selectedMap.set(e,t),this.__updateLinks(),this.multi?this.push(JSCompiler_renameProperty("selected",this),e):this.selected=this.selectedItem=e)}}}))(Re);class jn extends zn{static get is(){return"array-selector"}static get template(){return null}}customElements.define(jn.is,jn);const Bn=new Zs;window.ShadyCSS||(window.ShadyCSS={prepareTemplate(t,e,s){},prepareTemplateDom(t,e){},prepareTemplateStyles(t,e,s){},styleSubtree(t,e){Bn.processStyles(),xs(t,e)},styleElement(t){Bn.processStyles()},styleDocument(t){Bn.processStyles(),xs(document.body,t)},getComputedStyleValue:(t,e)=>As(t,e),flushCustomStyles(){},nativeCss:is,nativeShadow:ts,cssBuild:ss,disableRuntime:rs}),window.ShadyCSS.CustomStyleInterface=Bn;const qn=window.ShadyCSS.CustomStyleInterface;class $n extends HTMLElement{constructor(){super(),this._style=null,qn.addCustomStyle(this)}getStyle(){if(this._style)return this._style;const t=this.querySelector("style");if(!t)return null;this._style=t;const e=t.getAttribute("include");return e&&(t.removeAttribute("include"),t.textContent=function(t){let e=t.trim().split(/\s+/),s="";for(let t=0;t<e.length;t++)s+=vt(e[t]);return s}(e)+t.textContent),this.ownerDocument!==window.document&&window.document.head.appendChild(this),this._style}}window.customElements.define("custom-style",$n);const Yn=En(HTMLElement).prototype;export{Yn as Base,c as Debouncer,Ze as DomIf,Qe as DomRepeat,fn as FlattenedNodesObserver,kn as OptionalMutableDataBehavior,Dn as Polymer,Re as PolymerElement,qe as TemplateInstanceBase,Fn as Templatizer,ln as afterNextRender,o as animationFrame,an as beforeNextRender,un as calculateSplices,Dt as dashToCamelCase,d as dedupingMixin,Sn as dom,p as enqueueDebouncer,Ge as flush,ut as gestures,It as get,Me as html,a as idlePeriod,Nt as matches,l as microTask,xn as mixinBehaviors,Xe as templatize,i as timeOut,Ot as translate,v as useShadow};
\ No newline at end of file
diff --git a/third_party/polymer/v3_0/minify_polymer.py b/third_party/polymer/v3_0/minify_polymer.py
index e67181f..c7aabe8 100644
--- a/third_party/polymer/v3_0/minify_polymer.py
+++ b/third_party/polymer/v3_0/minify_polymer.py
@@ -50,6 +50,9 @@
     minified_js = os.path.join(tmp_out_dir, 'polymer_bundled.min.js')
     node.RunNode([
         node_modules.PathToTerser(), bundled_js,
+        '--compress',
+        '--mangle',
+        '--module',
         # TODO(dpapad): Figure out a way to deduplicate LICENSE headers. In the
         # meantime exclude such comments to reduce file size.
         '--comments', 'false',
diff --git a/third_party/protobuf/README.chromium b/third_party/protobuf/README.chromium
index abb7c5f..1bb5d59 100644
--- a/third_party/protobuf/README.chromium
+++ b/third_party/protobuf/README.chromium
@@ -97,3 +97,9 @@
   Imports
   https://github.com/protocolbuffers/protobuf/commit/ed8b2e6f62afee17e2f8249be3b9b69eb0666532
   to remove uses of std::iterator.
+
+- 0026-remove-sprintf.patch
+
+  Imports
+  https://github.com/protocolbuffers/protobuf/commit/c0fc2e881bc36aafb0bf539bf41889611370f60c
+  to remove use of sprintf.
diff --git a/third_party/protobuf/patches/0026-remove-sprintf.patch b/third_party/protobuf/patches/0026-remove-sprintf.patch
new file mode 100644
index 0000000..6629a6b
--- /dev/null
+++ b/third_party/protobuf/patches/0026-remove-sprintf.patch
@@ -0,0 +1,15 @@
+diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
+index 594c8eac6..f986b11e7 100644
+--- a/src/google/protobuf/stubs/strutil.cc
++++ b/src/google/protobuf/stubs/strutil.cc
+@@ -503,8 +503,8 @@ int CEscapeInternal(const char* src, int src_len, char* dest,
+              (last_hex_escape && isxdigit(*src)))) {
+           if (dest_len - used < 4) // need space for 4 letter escape
+             return -1;
+-          sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
+-                  static_cast<uint8_t>(*src));
++          snprintf(dest + used, 5, (use_hex ? "\\x%02x" : "\\%03o"),
++                   static_cast<uint8_t>(*src));
+           is_hex_escape = use_hex;
+           used += 4;
+         } else {
diff --git a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
index 2722594..9c133dd1 100644
--- a/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
+++ b/third_party/protobuf/src/google/protobuf/stubs/strutil.cc
@@ -504,8 +504,8 @@
              (last_hex_escape && isxdigit(*src)))) {
           if (dest_len - used < 4) // need space for 4 letter escape
             return -1;
-          sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
-                  static_cast<uint8>(*src));
+          snprintf(dest + used, 5, (use_hex ? "\\x%02x" : "\\%03o"),
+                   static_cast<uint8>(*src));
           is_hex_escape = use_hex;
           used += 4;
         } else {
diff --git a/third_party/rust/camino/v1/BUILD.gn b/third_party/rust/camino/v1/BUILD.gn
new file mode 100644
index 0000000..8042879
--- /dev/null
+++ b/third_party/rust/camino/v1/BUILD.gn
@@ -0,0 +1,32 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/cargo_crate.gni")
+
+cargo_crate("lib") {
+  crate_name = "camino"
+  epoch = "1"
+  crate_type = "rlib"
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
+  crate_root = "crate/src/lib.rs"
+
+  # Unit tests skipped. Generate with --with-tests to include them.
+  build_native_rust_unit_tests = false
+  sources = [ "crate/src/lib.rs" ]
+  edition = "2018"
+  cargo_pkg_version = "1.0.9"
+  cargo_pkg_authors = "Without Boats <saoirse@without.boats>, Ashley Williams <ashley666ashley@gmail.com>, Steve Klabnik <steve@steveklabnik.com>, Rain <rain@sunshowers.io>"
+  cargo_pkg_name = "camino"
+  cargo_pkg_description = "UTF-8 paths"
+  deps = [ "//third_party/rust/serde/v1:lib" ]
+  features = [
+    "serde",
+    "serde1",
+  ]
+  build_root = "crate/build.rs"
+  build_sources = [ "crate/build.rs" ]
+}
diff --git a/third_party/rust/camino/v1/README.chromium b/third_party/rust/camino/v1/README.chromium
new file mode 100644
index 0000000..5814b9f
--- /dev/null
+++ b/third_party/rust/camino/v1/README.chromium
@@ -0,0 +1,6 @@
+Name: camino
+URL: https://crates.io/crates/camino
+Description: UTF-8 paths
+Version: 1.0.9
+Security Critical: no
+License: Apache 2.0
diff --git a/third_party/rust/camino/v1/crate/.cargo_vcs_info.json b/third_party/rust/camino/v1/crate/.cargo_vcs_info.json
new file mode 100644
index 0000000..c1ea121
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "09448fddde9f8ad1fe7981ad406356c5c94b8598"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/third_party/rust/camino/v1/crate/.gitignore b/third_party/rust/camino/v1/crate/.gitignore
new file mode 100644
index 0000000..96ef6c0
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/.gitignore
@@ -0,0 +1,2 @@
+/target
+Cargo.lock
diff --git a/third_party/rust/camino/v1/crate/CHANGELOG.md b/third_party/rust/camino/v1/crate/CHANGELOG.md
new file mode 100644
index 0000000..b9a04de
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/CHANGELOG.md
@@ -0,0 +1,95 @@
+# Changelog
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+## [1.0.9] - 2022-05-19
+
+### Fixed
+
+- Documentation fixes.
+
+## [1.0.8] - 2022-05-09
+
+### Added
+
+- New methods `canonicalize_utf8`, `read_link_utf8` and `read_dir_utf8` return `Utf8PathBuf`s, erroring out if a resulting path is not valid UTF-8.
+- New feature `proptest1` introduces proptest `Arbitrary` impls for `Utf8PathBuf` and
+  `Box<Utf8Path>` ([#18], thanks [mcronce](https://github.com/mcronce) for your first contribution!)
+  
+[#18]: https://github.com/camino-rs/camino/pull/18
+
+## [1.0.7] - 2022-01-16
+
+### Added
+
+- `Utf8Path::is_symlink` checks whether a path is a symlink. Note that while `std::path::Path` only
+  provides this method for version 1.58 and above, `camino` polyfills the method for all Rust versions
+  it supports.
+
+### Changed
+
+- Update repository links to new location [camino-rs/camino](https://github.com/camino-rs/camino).
+- Update `structopt` example to clap 3's builtin derive feature.
+  (camino continues to work with structopt as before.)
+
+## [1.0.6] - 2022-01-16
+
+(This release was yanked due to a publishing issue.)
+
+## [1.0.5] - 2021-07-27
+
+### Added
+
+- `Utf8PathBuf::into_std_path_buf` converts a `Utf8PathBuf` to a `PathBuf`; equivalent to the
+  `From<Utf8PathBuf> for PathBuf` impl, but may aid in type inference.
+- `Utf8Path::as_std_path` converts a `Utf8Path` to a `Path`; equivalent to the
+  `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference.
+
+## [1.0.4] - 2021-03-19
+
+### Fixed
+
+- `Hash` impls for `Utf8PathBuf` and `Utf8Path` now match as required by the `Borrow` contract ([#9]).
+
+[#9]: https://github.com/camino-rs/camino/issues/9
+
+## [1.0.3] - 2021-03-11
+
+### Added
+
+- `TryFrom<PathBuf> for Utf8PathBuf` and `TryFrom<&Path> for &Utf8Path`, both of which return new error types ([#6]).
+- `AsRef<Utf8Path>`, `AsRef<Path>`, `AsRef<str>` and `AsRef<OsStr>` impls for `Utf8Components`, `Utf8Component` and
+  `Iter`.
+
+[#6]: https://github.com/camino-rs/camino/issues/6
+
+## [1.0.2] - 2021-03-02
+
+### Added
+
+- `From` impls for converting a `&Utf8Path` or a `Utf8PathBuf` into `Box<Path>`, `Rc<Path>`, `Arc<Path>` and `Cow<'a, Path>`.
+- `PartialEq` and `PartialOrd` implementations comparing `Utf8Path` and `Utf8PathBuf` with `Path`, `PathBuf` and its
+  variants, and comparing `OsStr`, `OsString` and its variants.
+
+## [1.0.1] - 2021-02-25
+
+### Added
+
+- More `PartialEq` and `PartialOrd` implementations.
+- MSRV lowered to 1.34.
+
+## [1.0.0] - 2021-02-23
+
+Initial release.
+
+[1.0.9]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.9
+[1.0.8]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.8
+[1.0.7]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.7
+[1.0.6]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.6
+[1.0.5]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.5
+[1.0.4]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.4
+[1.0.3]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.3
+[1.0.2]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.2
+[1.0.1]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.1
+[1.0.0]: https://github.com/camino-rs/camino/releases/tag/camino-1.0.0
diff --git a/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md b/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..2ea2606d
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/CODE_OF_CONDUCT.md
@@ -0,0 +1,133 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at the email
+address: [codeofconduct@sunshowers.io](mailto:codeofconduct@sunshowers.io).
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+[https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][v2.0].
+
+Community Impact Guidelines were inspired by 
+[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][FAQ]. Translations are available 
+at [https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.0]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html
+[Mozilla CoC]: https://github.com/mozilla/diversity
+[FAQ]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
+
diff --git a/third_party/rust/camino/v1/crate/Cargo.toml b/third_party/rust/camino/v1/crate/Cargo.toml
new file mode 100644
index 0000000..cd2bd9f
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/Cargo.toml
@@ -0,0 +1,58 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "camino"
+version = "1.0.9"
+authors = [
+    "Without Boats <saoirse@without.boats>",
+    "Ashley Williams <ashley666ashley@gmail.com>",
+    "Steve Klabnik <steve@steveklabnik.com>",
+    "Rain <rain@sunshowers.io>",
+]
+exclude = [
+    ".cargo/**/*",
+    ".github/**/*",
+]
+description = "UTF-8 paths"
+documentation = "https://docs.rs/camino"
+readme = "README.md"
+keywords = [
+    "paths",
+    "utf8",
+    "unicode",
+    "filesystem",
+]
+categories = [
+    "development-tools",
+    "filesystem",
+    "os",
+]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/camino-rs/camino"
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg=doc_cfg"]
+
+[dependencies.proptest]
+version = "1.0.0"
+optional = true
+
+[dependencies.serde]
+version = "1"
+features = ["derive"]
+optional = true
+
+[features]
+proptest1 = ["proptest"]
+serde1 = ["serde"]
diff --git a/third_party/rust/camino/v1/crate/Cargo.toml.orig b/third_party/rust/camino/v1/crate/Cargo.toml.orig
new file mode 100644
index 0000000..17f7523
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/Cargo.toml.orig
@@ -0,0 +1,33 @@
+[workspace]
+members = [".", "camino-examples"]
+
+[package]
+name = "camino"
+description = "UTF-8 paths"
+version = "1.0.9"
+license = "MIT OR Apache-2.0"
+readme = "README.md"
+keywords = ["paths", "utf8", "unicode", "filesystem"]
+categories = ["development-tools", "filesystem", "os"]
+repository = "https://github.com/camino-rs/camino"
+documentation = "https://docs.rs/camino"
+authors = [
+    "Without Boats <saoirse@without.boats>",
+    "Ashley Williams <ashley666ashley@gmail.com>",
+    "Steve Klabnik <steve@steveklabnik.com>",
+    "Rain <rain@sunshowers.io>",
+]
+edition = "2018"
+exclude = [".cargo/**/*", ".github/**/*"]
+
+[package.metadata.docs.rs]
+all-features = true
+rustdoc-args = ["--cfg=doc_cfg"]
+
+[dependencies]
+proptest = { version = "1.0.0", optional = true }
+serde = { version = "1", features = ["derive"], optional = true }
+
+[features]
+serde1 = ["serde"]
+proptest1 = ["proptest"]
diff --git a/third_party/rust/camino/v1/crate/LICENSE-APACHE b/third_party/rust/camino/v1/crate/LICENSE-APACHE
new file mode 100644
index 0000000..16fe87b
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              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.
diff --git a/third_party/rust/camino/v1/crate/LICENSE-MIT b/third_party/rust/camino/v1/crate/LICENSE-MIT
new file mode 100644
index 0000000..31aa7938
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/LICENSE-MIT
@@ -0,0 +1,23 @@
+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
+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.
diff --git a/third_party/rust/camino/v1/crate/README.md b/third_party/rust/camino/v1/crate/README.md
new file mode 100644
index 0000000..9fad93a
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/README.md
@@ -0,0 +1,132 @@
+# camino - UTF-8 encoded paths
+
+[![camino on crates.io](https://img.shields.io/crates/v/camino)](https://crates.io/crates/camino)
+[![crates.io download count](https://img.shields.io/crates/d/camino)](https://crates.io/crates/camino)
+[![Documentation (latest release)](https://img.shields.io/badge/docs-latest%20version-brightgreen.svg)](https://docs.rs/camino)
+[![Documentation (main)](https://img.shields.io/badge/docs-main-purple.svg)](https://camino-rs.github.io/camino/rustdoc/camino/)
+[![License](https://img.shields.io/badge/license-Apache-green.svg)](LICENSE-APACHE)
+[![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE-MIT)
+
+This repository contains the source code for `camino`, an extension of the `std::path` module that adds new
+[`Utf8PathBuf`] and [`Utf8Path`] types.
+
+## What is camino?
+
+`camino`'s [`Utf8PathBuf`] and [`Utf8Path`] types are like the standard library's [`PathBuf`] and [`Path`] types, except
+they  are guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their
+contents as strings, they implement `Display`, etc.
+
+The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library,
+since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a
+number of reasons:
+* Unicode won. There are still some legacy codebases that store paths in encodings like [Shift JIS], but most
+  have been converted to Unicode at this point.
+* Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths
+  as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32
+  API boundaries.)
+* There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such
+  system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers.
+* The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22) asks: given a
+  Makefile or other metadata file (such as `Cargo.toml`) that lists the names of other files, how should the names in
+  the Makefile be matched with the ones on disk? This has *no general, cross-platform solution* in systems that support
+  non-UTF-8 paths. However, restricting paths to UTF-8 eliminates this problem.
+
+[Shift JIS]: https://en.wikipedia.org/wiki/Shift_JIS
+
+Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s
+as  necessary. However, because this invariant is not encoded in the `Path` type, conversions such as
+`path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience.
+
+Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them
+as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions.
+
+## Examples
+
+The documentation for [`Utf8PathBuf`] and [`Utf8Path`] contains several examples.
+
+For examples of how to use `camino` with other libraries like `serde` and `clap`, see the [`camino-examples`] directory.
+
+## API design
+
+`camino` is a very thin wrapper around `std::path`. [`Utf8Path`] and [`Utf8PathBuf`] are drop-in replacements
+for [`Path`] and [`PathBuf`].
+
+Most APIs are the same, but those at the boundary with `str` are different. Some examples:
+* `Path::to_str() -> Option<&str>` has been renamed to `Utf8Path::as_str() -> &str`.
+* [`Utf8Path`] implements `Display`, and `Path::display()` has been removed.
+* Iterating over a [`Utf8Path`] returns `&str`, not `&OsStr`.
+
+Every [`Utf8Path`] is a valid [`Path`], so [`Utf8Path`] implements `AsRef<Path>`. Any APIs that accept `impl AsRef<Path>`
+will continue to work with [`Utf8Path`] instances.
+
+## Should you use camino?
+
+`camino` trades off some utility for a great deal of simplicity. Whether `camino` is appropriate for a project or not
+is ultimately a case-by-case decision. Here are some general guidelines that may help.
+
+*You should consider using camino if...*
+
+* **You're building portable, cross-platform software.** While both Unix and Windows platforms support different kinds
+  of non-Unicode paths, Unicode is the common subset that's supported across them.
+* **Your system has files that contain the names of other files.** If you don't use UTF-8 paths, you will run into the
+  makefile problem described above, which has no general, cross-platform solution.
+* **You're interacting with existing systems that already assume UTF-8 paths.** In that case you won't be adding any new
+  burdens on downstream consumers.
+* **You're building something brand new and are willing to ask your users to rename their paths if necessary.** Projects
+  that don't have to worry about legacy compatibility have more flexibility in choosing what paths they support.
+  
+In general, using camino is the right choice for most projects.
+
+*You should **NOT** use camino, if...*
+
+* **You're writing a core system utility.** If you're writing, say, an `mv` or `cat` replacement, you should
+  **not** use camino. Instead, use [`std::path::Path`] and add extensive tests for non-UTF-8 paths.
+* **You have legacy compatibility constraints.** For example, Git supports non-UTF-8 paths. If your tool needs to handle
+  arbitrary Git repositories, it should use its own path type that's a wrapper around `Vec<u8>`. 
+  * [`std::path::Path`] supports arbitrary bytestrings [on Unix] but not on Windows.
+* **There's some other reason you need to support non-UTF-8 paths.** Some tools like disk recovery utilities need to
+  handle potentially corrupt filenames: only being able to handle UTF-8 paths would greatly diminish their utility.
+
+[on Unix]: https://doc.rust-lang.org/std/os/unix/ffi/index.html
+
+## Optional features
+
+By default, `camino` has **no dependencies** other than `std`. There are some optional features that enable
+dependencies:
+* `serde1` adds serde [`Serialize`] and [`Deserialize`] impls for [`Utf8PathBuf`] and [`Utf8Path`]
+  (zero-copy).
+* `proptest1` adds [proptest](https://altsysrq.github.io/proptest-book/) [`Arbitrary`]
+  implementations for [`Utf8PathBuf`] and `Box<Utf8Path>`.
+
+## Rust version support
+
+The minimum supported Rust version (MSRV) for `camino` with default features is **1.34**. This project is tested in CI
+against the latest stable version of Rust and the MSRV.
+* *Stable APIs* added in later Rust versions are supported either through conditional compilation in `build.rs`, or through backfills that also work on older versions.
+* *Deprecations* are kept in sync with the version of Rust they're added in.
+* *Unstable APIs* are currently not supported. Please
+  [file an issue on GitHub](https://github.com/camino-rs/camino/issues/new) if you need an unstable API.
+
+`camino` is designed to be a core library and has a conservative MSRV policy. MSRV increases will only happen for
+a compelling enough reason, and will involve at least a minor version bump.
+
+Optional features may pull in dependencies that require a newer version of Rust.
+
+## License
+
+This project is available under the terms of either the [Apache 2.0 license](LICENSE-APACHE) or the [MIT
+license](LICENSE-MIT).
+
+This project's documentation is adapted from [The Rust Programming Language](https://github.com/rust-lang/rust/), which is
+available under the terms of either the [Apache 2.0 license](https://github.com/rust-lang/rust/blob/master/LICENSE-APACHE)
+or the [MIT license](https://github.com/rust-lang/rust/blob/master/LICENSE-MIT).
+
+[`Utf8PathBuf`]: https://docs.rs/camino/*/camino/struct.Utf8PathBuf.html
+[`Utf8Path`]: https://docs.rs/camino/*/camino/struct.Utf8Path.html
+[`PathBuf`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html
+[`Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
+[`std::path::Path`]: https://doc.rust-lang.org/std/path/struct.Path.html
+[`Serialize`]: https://docs.rs/serde/1/serde/trait.Serialize.html
+[`Deserialize`]: https://docs.rs/serde/1/serde/trait.Deserialize.html
+[`camino-examples`]: https://github.com/camino-rs/camino/tree/main/camino-examples
+[`Arbitrary`]: https://docs.rs/proptest/1/proptest/arbitrary/trait.Arbitrary.html
diff --git a/third_party/rust/camino/v1/crate/build.rs b/third_party/rust/camino/v1/crate/build.rs
new file mode 100644
index 0000000..bc3e448
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/build.rs
@@ -0,0 +1,40 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+//! Adapted from
+//! https://github.com/dtolnay/syn/blob/a54fb0098c6679f1312113ae2eec0305c51c7390/build.rs.
+
+use std::{env, process::Command, str};
+
+// The rustc-cfg strings below are *not* public API. Please let us know by
+// opening a GitHub issue if your build environment requires some way to enable
+// these cfgs other than by executing our build script.
+fn main() {
+    let compiler = match rustc_version() {
+        Some(compiler) => compiler,
+        None => return,
+    };
+
+    // NOTE:
+    // Adding a new cfg gated by Rust version MUST be accompanied by an addition to the matrix in
+    // .github/workflows/ci.yml.
+    if compiler.minor >= 44 {
+        println!("cargo:rustc-cfg=path_buf_capacity");
+    }
+}
+
+struct Compiler {
+    minor: u32,
+}
+
+fn rustc_version() -> Option<Compiler> {
+    let rustc = env::var_os("RUSTC")?;
+    let output = Command::new(rustc).arg("--version").output().ok()?;
+    let version = str::from_utf8(&output.stdout).ok()?;
+    let mut pieces = version.split('.');
+    if pieces.next() != Some("rustc 1") {
+        return None;
+    }
+    let minor = pieces.next()?.parse().ok()?;
+    Some(Compiler { minor })
+}
diff --git a/third_party/rust/camino/v1/crate/clippy.toml b/third_party/rust/camino/v1/crate/clippy.toml
new file mode 100644
index 0000000..b32f6d50a
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/clippy.toml
@@ -0,0 +1 @@
+msrv = "1.34.0"
diff --git a/third_party/rust/camino/v1/crate/rustfmt.toml b/third_party/rust/camino/v1/crate/rustfmt.toml
new file mode 100644
index 0000000..80eeb40
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/rustfmt.toml
@@ -0,0 +1,2 @@
+edition = "2018"
+use_field_init_shorthand = true
diff --git a/third_party/rust/camino/v1/crate/src/lib.rs b/third_party/rust/camino/v1/crate/src/lib.rs
new file mode 100644
index 0000000..4a1b6df
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/src/lib.rs
@@ -0,0 +1,2773 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+#![warn(missing_docs)]
+#![cfg_attr(doc_cfg, feature(doc_cfg, doc_auto_cfg))]
+
+//! UTF-8 encoded paths.
+//!
+//! `camino` is an extension of the `std::path` module that adds new [`Utf8PathBuf`] and [`Utf8Path`]
+//! types. These are like the standard library's [`PathBuf`] and [`Path`] types, except they are
+//! guaranteed to only contain UTF-8 encoded data. Therefore, they expose the ability to get their
+//! contents as strings, they implement `Display`, etc.
+//!
+//! The `std::path` types are not guaranteed to be valid UTF-8. This is the right decision for the standard library,
+//! since it must be as general as possible. However, on all platforms, non-Unicode paths are vanishingly uncommon for a
+//! number of reasons:
+//! * Unicode won. There are still some legacy codebases that store paths in encodings like Shift-JIS, but most
+//!   have been converted to Unicode at this point.
+//! * Unicode is the common subset of supported paths across Windows and Unix platforms. (On Windows, Rust stores paths
+//!   as [an extension to UTF-8](https://simonsapin.github.io/wtf-8/), and converts them to UTF-16 at Win32
+//!   API boundaries.)
+//! * There are already many systems, such as Cargo, that only support UTF-8 paths. If your own tool interacts with any such
+//!   system, you can assume that paths are valid UTF-8 without creating any additional burdens on consumers.
+//! * The ["makefile problem"](https://www.mercurial-scm.org/wiki/EncodingStrategy#The_.22makefile_problem.22)
+//!   (which also applies to `Cargo.toml`, and any other metadata file that lists the names of other files) has *no general,
+//!   cross-platform solution* in systems that support non-UTF-8 paths. However, restricting paths to UTF-8 eliminates
+//!   this problem.
+//!
+//! Therefore, many programs that want to manipulate paths *do* assume they contain UTF-8 data, and convert them to `str`s
+//! as  necessary. However, because this invariant is not encoded in the `Path` type, conversions such as
+//! `path.to_str().unwrap()` need to be repeated again and again, creating a frustrating experience.
+//!
+//! Instead, `camino` allows you to check that your paths are UTF-8 *once*, and then manipulate them
+//! as valid UTF-8 from there on, avoiding repeated lossy and confusing conversions.
+
+use std::{
+    borrow::{Borrow, Cow},
+    cmp::Ordering,
+    convert::{Infallible, TryFrom, TryInto},
+    error,
+    ffi::{OsStr, OsString},
+    fmt,
+    fs::{self, Metadata},
+    hash::{Hash, Hasher},
+    io,
+    iter::FusedIterator,
+    ops::Deref,
+    path::*,
+    rc::Rc,
+    str::FromStr,
+    sync::Arc,
+};
+
+#[cfg(feature = "proptest1")]
+mod proptest_impls;
+#[cfg(feature = "serde1")]
+mod serde_impls;
+#[cfg(test)]
+mod tests;
+
+/// An owned, mutable UTF-8 path (akin to [`String`]).
+///
+/// This type provides methods like [`push`] and [`set_extension`] that mutate
+/// the path in place. It also implements [`Deref`] to [`Utf8Path`], meaning that
+/// all methods on [`Utf8Path`] slices are available on `Utf8PathBuf` values as well.
+///
+/// [`push`]: Utf8PathBuf::push
+/// [`set_extension`]: Utf8PathBuf::set_extension
+///
+/// # Examples
+///
+/// You can use [`push`] to build up a `Utf8PathBuf` from
+/// components:
+///
+/// ```
+/// use camino::Utf8PathBuf;
+///
+/// let mut path = Utf8PathBuf::new();
+///
+/// path.push(r"C:\");
+/// path.push("windows");
+/// path.push("system32");
+///
+/// path.set_extension("dll");
+/// ```
+///
+/// However, [`push`] is best used for dynamic situations. This is a better way
+/// to do this when you know all of the components ahead of time:
+///
+/// ```
+/// use camino::Utf8PathBuf;
+///
+/// let path: Utf8PathBuf = [r"C:\", "windows", "system32.dll"].iter().collect();
+/// ```
+///
+/// We can still do better than this! Since these are all strings, we can use
+/// `From::from`:
+///
+/// ```
+/// use camino::Utf8PathBuf;
+///
+/// let path = Utf8PathBuf::from(r"C:\windows\system32.dll");
+/// ```
+///
+/// Which method works best depends on what kind of situation you're in.
+// NB: Internal PathBuf must only contain utf8 data
+#[derive(Clone, Default)]
+#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
+#[cfg_attr(feature = "serde1", serde(transparent))]
+#[repr(transparent)]
+pub struct Utf8PathBuf(PathBuf);
+
+impl Utf8PathBuf {
+    /// Allocates an empty `Utf8PathBuf`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let path = Utf8PathBuf::new();
+    /// ```
+    pub fn new() -> Utf8PathBuf {
+        Utf8PathBuf(PathBuf::new())
+    }
+
+    /// Creates a new `Utf8PathBuf` from a `PathBuf` containing valid UTF-8 characters.
+    ///
+    /// Errors with the original `PathBuf` if it is not valid UTF-8.
+    ///
+    /// For a version that returns a type that implements [`std::error::Error`], use the
+    /// `TryFrom<PathBuf>` impl.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    /// use std::ffi::OsStr;
+    /// # #[cfg(unix)]
+    /// use std::os::unix::ffi::OsStrExt;
+    /// use std::path::PathBuf;
+    ///
+    /// let unicode_path = PathBuf::from("/valid/unicode");
+    /// Utf8PathBuf::from_path_buf(unicode_path).expect("valid Unicode path succeeded");
+    ///
+    /// // Paths on Unix can be non-UTF-8.
+    /// # #[cfg(unix)]
+    /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF");
+    /// # #[cfg(unix)]
+    /// let non_unicode_path = PathBuf::from(non_unicode_str);
+    /// # #[cfg(unix)]
+    /// Utf8PathBuf::from_path_buf(non_unicode_path).expect_err("non-Unicode path failed");
+    /// ```
+    pub fn from_path_buf(path: PathBuf) -> Result<Utf8PathBuf, PathBuf> {
+        match path.into_os_string().into_string() {
+            Ok(string) => Ok(Utf8PathBuf::from(string)),
+            Err(os_string) => Err(PathBuf::from(os_string)),
+        }
+    }
+
+    /// Converts a `Utf8PathBuf` to a [`PathBuf`].
+    ///
+    /// This is equivalent to the `From<Utf8PathBuf> for PathBuf` impl, but may aid in type
+    /// inference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    /// use std::path::PathBuf;
+    ///
+    /// let utf8_path_buf = Utf8PathBuf::from("foo.txt");
+    /// let std_path_buf = utf8_path_buf.into_std_path_buf();
+    /// assert_eq!(std_path_buf.to_str(), Some("foo.txt"));
+    ///
+    /// // Convert back to a Utf8PathBuf.
+    /// let new_utf8_path_buf = Utf8PathBuf::from_path_buf(std_path_buf).unwrap();
+    /// assert_eq!(new_utf8_path_buf, "foo.txt");
+    /// ```
+    pub fn into_std_path_buf(self) -> PathBuf {
+        self.into()
+    }
+
+    /// Creates a new `Utf8PathBuf` with a given capacity used to create the internal [`PathBuf`].
+    /// See [`with_capacity`] defined on [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let mut path = Utf8PathBuf::with_capacity(10);
+    /// let capacity = path.capacity();
+    ///
+    /// // This push is done without reallocating
+    /// path.push(r"C:\");
+    ///
+    /// assert_eq!(capacity, path.capacity());
+    /// ```
+    ///
+    /// [`with_capacity`]: PathBuf::with_capacity
+    #[cfg(path_buf_capacity)]
+    pub fn with_capacity(capacity: usize) -> Utf8PathBuf {
+        Utf8PathBuf(PathBuf::with_capacity(capacity))
+    }
+
+    /// Coerces to a [`Utf8Path`] slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let p = Utf8PathBuf::from("/test");
+    /// assert_eq!(Utf8Path::new("/test"), p.as_path());
+    /// ```
+    pub fn as_path(&self) -> &Utf8Path {
+        // SAFETY: every Utf8PathBuf constructor ensures that self is valid UTF-8
+        unsafe { Utf8Path::assume_utf8(&*self.0) }
+    }
+
+    /// Extends `self` with `path`.
+    ///
+    /// If `path` is absolute, it replaces the current path.
+    ///
+    /// On Windows:
+    ///
+    /// * if `path` has a root but no prefix (e.g., `\windows`), it
+    ///   replaces everything except for the prefix (if any) of `self`.
+    /// * if `path` has a prefix but no root, it replaces `self`.
+    ///
+    /// # Examples
+    ///
+    /// Pushing a relative path extends the existing path:
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let mut path = Utf8PathBuf::from("/tmp");
+    /// path.push("file.bk");
+    /// assert_eq!(path, Utf8PathBuf::from("/tmp/file.bk"));
+    /// ```
+    ///
+    /// Pushing an absolute path replaces the existing path:
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let mut path = Utf8PathBuf::from("/tmp");
+    /// path.push("/etc");
+    /// assert_eq!(path, Utf8PathBuf::from("/etc"));
+    /// ```
+    pub fn push(&mut self, path: impl AsRef<Utf8Path>) {
+        self.0.push(&path.as_ref().0)
+    }
+
+    /// Truncates `self` to [`self.parent`].
+    ///
+    /// Returns `false` and does nothing if [`self.parent`] is [`None`].
+    /// Otherwise, returns `true`.
+    ///
+    /// [`self.parent`]: Utf8Path::parent
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let mut p = Utf8PathBuf::from("/spirited/away.rs");
+    ///
+    /// p.pop();
+    /// assert_eq!(Utf8Path::new("/spirited"), p);
+    /// p.pop();
+    /// assert_eq!(Utf8Path::new("/"), p);
+    /// ```
+    pub fn pop(&mut self) -> bool {
+        self.0.pop()
+    }
+
+    /// Updates [`self.file_name`] to `file_name`.
+    ///
+    /// If [`self.file_name`] was [`None`], this is equivalent to pushing
+    /// `file_name`.
+    ///
+    /// Otherwise it is equivalent to calling [`pop`] and then pushing
+    /// `file_name`. The new path will be a sibling of the original path.
+    /// (That is, it will have the same parent.)
+    ///
+    /// [`self.file_name`]: Utf8Path::file_name
+    /// [`pop`]: Utf8PathBuf::pop
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let mut buf = Utf8PathBuf::from("/");
+    /// assert_eq!(buf.file_name(), None);
+    /// buf.set_file_name("bar");
+    /// assert_eq!(buf, Utf8PathBuf::from("/bar"));
+    /// assert!(buf.file_name().is_some());
+    /// buf.set_file_name("baz.txt");
+    /// assert_eq!(buf, Utf8PathBuf::from("/baz.txt"));
+    /// ```
+    pub fn set_file_name(&mut self, file_name: impl AsRef<str>) {
+        self.0.set_file_name(file_name.as_ref())
+    }
+
+    /// Updates [`self.extension`] to `extension`.
+    ///
+    /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
+    /// returns `true` and updates the extension otherwise.
+    ///
+    /// If [`self.extension`] is [`None`], the extension is added; otherwise
+    /// it is replaced.
+    ///
+    /// [`self.file_name`]: Utf8Path::file_name
+    /// [`self.extension`]: Utf8Path::extension
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let mut p = Utf8PathBuf::from("/feel/the");
+    ///
+    /// p.set_extension("force");
+    /// assert_eq!(Utf8Path::new("/feel/the.force"), p.as_path());
+    ///
+    /// p.set_extension("dark_side");
+    /// assert_eq!(Utf8Path::new("/feel/the.dark_side"), p.as_path());
+    /// ```
+    pub fn set_extension(&mut self, extension: impl AsRef<str>) -> bool {
+        self.0.set_extension(extension.as_ref())
+    }
+
+    /// Consumes the `Utf8PathBuf`, yielding its internal [`String`] storage.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    ///
+    /// let p = Utf8PathBuf::from("/the/head");
+    /// let s = p.into_string();
+    /// assert_eq!(s, "/the/head");
+    /// ```
+    pub fn into_string(self) -> String {
+        self.into_os_string().into_string().unwrap()
+    }
+
+    /// Consumes the `Utf8PathBuf`, yielding its internal [`OsString`] storage.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8PathBuf;
+    /// use std::ffi::OsStr;
+    ///
+    /// let p = Utf8PathBuf::from("/the/head");
+    /// let s = p.into_os_string();
+    /// assert_eq!(s, OsStr::new("/the/head"));
+    /// ```
+    pub fn into_os_string(self) -> OsString {
+        self.0.into_os_string()
+    }
+
+    /// Converts this `Utf8PathBuf` into a [boxed](Box) [`Utf8Path`].
+    pub fn into_boxed_path(self) -> Box<Utf8Path> {
+        let ptr = Box::into_raw(self.0.into_boxed_path()) as *mut Utf8Path;
+        // SAFETY:
+        // * self is valid UTF-8
+        // * ptr was constructed by consuming self so it represents an owned path
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to
+        //   *mut Utf8Path is valid
+        unsafe { Box::from_raw(ptr) }
+    }
+
+    /// Invokes [`capacity`] on the underlying instance of [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// [`capacity`]: PathBuf::capacity
+    #[cfg(path_buf_capacity)]
+    pub fn capacity(&self) -> usize {
+        self.0.capacity()
+    }
+
+    /// Invokes [`clear`] on the underlying instance of [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// [`clear`]: PathBuf::clear
+    #[cfg(path_buf_capacity)]
+    pub fn clear(&mut self) {
+        self.0.clear()
+    }
+
+    /// Invokes [`reserve`] on the underlying instance of [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// [`reserve`]: PathBuf::reserve
+    #[cfg(path_buf_capacity)]
+    pub fn reserve(&mut self, additional: usize) {
+        self.0.reserve(additional)
+    }
+
+    /// Invokes [`reserve_exact`] on the underlying instance of [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// [`reserve_exact`]: PathBuf::reserve_exact
+    #[cfg(path_buf_capacity)]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.0.reserve_exact(additional)
+    }
+
+    /// Invokes [`shrink_to_fit`] on the underlying instance of [`PathBuf`].
+    ///
+    /// *Requires Rust 1.44 or newer.*
+    ///
+    /// [`shrink_to_fit`]: PathBuf::shrink_to_fit
+    #[cfg(path_buf_capacity)]
+    pub fn shrink_to_fit(&mut self) {
+        self.0.shrink_to_fit()
+    }
+}
+
+impl Deref for Utf8PathBuf {
+    type Target = Utf8Path;
+
+    fn deref(&self) -> &Utf8Path {
+        self.as_path()
+    }
+}
+
+impl fmt::Debug for Utf8PathBuf {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&**self, f)
+    }
+}
+
+impl fmt::Display for Utf8PathBuf {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
+impl<P: AsRef<Utf8Path>> Extend<P> for Utf8PathBuf {
+    fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
+        for path in iter {
+            self.push(path);
+        }
+    }
+}
+
+/// A slice of a UTF-8 path (akin to [`str`]).
+///
+/// This type supports a number of operations for inspecting a path, including
+/// breaking the path into its components (separated by `/` on Unix and by either
+/// `/` or `\` on Windows), extracting the file name, determining whether the path
+/// is absolute, and so on.
+///
+/// This is an *unsized* type, meaning that it must always be used behind a
+/// pointer like `&` or [`Box`]. For an owned version of this type,
+/// see [`Utf8PathBuf`].
+///
+/// # Examples
+///
+/// ```
+/// use camino::Utf8Path;
+///
+/// // Note: this example does work on Windows
+/// let path = Utf8Path::new("./foo/bar.txt");
+///
+/// let parent = path.parent();
+/// assert_eq!(parent, Some(Utf8Path::new("./foo")));
+///
+/// let file_stem = path.file_stem();
+/// assert_eq!(file_stem, Some("bar"));
+///
+/// let extension = path.extension();
+/// assert_eq!(extension, Some("txt"));
+/// ```
+// NB: Internal Path must only contain utf8 data
+#[repr(transparent)]
+pub struct Utf8Path(Path);
+
+impl Utf8Path {
+    /// Directly wraps a string slice as a `Utf8Path` slice.
+    ///
+    /// This is a cost-free conversion.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// Utf8Path::new("foo.txt");
+    /// ```
+    ///
+    /// You can create `Utf8Path`s from `String`s, or even other `Utf8Path`s:
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let string = String::from("foo.txt");
+    /// let from_string = Utf8Path::new(&string);
+    /// let from_path = Utf8Path::new(&from_string);
+    /// assert_eq!(from_string, from_path);
+    /// ```
+    pub fn new(s: &(impl AsRef<str> + ?Sized)) -> &Utf8Path {
+        let path = Path::new(s.as_ref());
+        // SAFETY: s is a str which means it is always valid UTF-8
+        unsafe { Utf8Path::assume_utf8(path) }
+    }
+
+    /// Converts a [`Path`] to a `Utf8Path`.
+    ///
+    /// Returns `None` if the path is not valid UTF-8.
+    ///
+    /// For a version that returns a type that implements [`std::error::Error`], use the
+    /// `TryFrom<&Path>` impl.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    /// use std::ffi::OsStr;
+    /// # #[cfg(unix)]
+    /// use std::os::unix::ffi::OsStrExt;
+    /// use std::path::Path;
+    ///
+    /// let unicode_path = Path::new("/valid/unicode");
+    /// Utf8Path::from_path(unicode_path).expect("valid Unicode path succeeded");
+    ///
+    /// // Paths on Unix can be non-UTF-8.
+    /// # #[cfg(unix)]
+    /// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF");
+    /// # #[cfg(unix)]
+    /// let non_unicode_path = Path::new(non_unicode_str);
+    /// # #[cfg(unix)]
+    /// assert!(Utf8Path::from_path(non_unicode_path).is_none(), "non-Unicode path failed");
+    /// ```
+    pub fn from_path(path: &Path) -> Option<&Utf8Path> {
+        path.as_os_str().to_str().map(Utf8Path::new)
+    }
+
+    /// Converts a `Utf8Path` to a [`Path`].
+    ///
+    /// This is equivalent to the `AsRef<&Path> for &Utf8Path` impl, but may aid in type inference.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    /// use std::path::Path;
+    ///
+    /// let utf8_path = Utf8Path::new("foo.txt");
+    /// let std_path: &Path = utf8_path.as_std_path();
+    /// assert_eq!(std_path.to_str(), Some("foo.txt"));
+    ///
+    /// // Convert back to a Utf8Path.
+    /// let new_utf8_path = Utf8Path::from_path(std_path).unwrap();
+    /// assert_eq!(new_utf8_path, "foo.txt");
+    /// ```
+    pub fn as_std_path(&self) -> &Path {
+        self.as_ref()
+    }
+
+    /// Yields the underlying [`str`] slice.
+    ///
+    /// Unlike [`Path::to_str`], this always returns a slice because the contents of a `Utf8Path`
+    /// are guaranteed to be valid UTF-8.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let s = Utf8Path::new("foo.txt").as_str();
+    /// assert_eq!(s, "foo.txt");
+    /// ```
+    ///
+    /// [`str`]: str
+    pub fn as_str(&self) -> &str {
+        // SAFETY: every Utf8Path constructor ensures that self is valid UTF-8
+        unsafe { assume_utf8(self.as_os_str()) }
+    }
+
+    /// Yields the underlying [`OsStr`] slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let os_str = Utf8Path::new("foo.txt").as_os_str();
+    /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
+    /// ```
+    pub fn as_os_str(&self) -> &OsStr {
+        self.0.as_os_str()
+    }
+
+    /// Converts a `Utf8Path` to an owned [`Utf8PathBuf`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let path_buf = Utf8Path::new("foo.txt").to_path_buf();
+    /// assert_eq!(path_buf, Utf8PathBuf::from("foo.txt"));
+    /// ```
+    pub fn to_path_buf(&self) -> Utf8PathBuf {
+        Utf8PathBuf(self.0.to_path_buf())
+    }
+
+    /// Returns `true` if the `Utf8Path` is absolute, i.e., if it is independent of
+    /// the current directory.
+    ///
+    /// * On Unix, a path is absolute if it starts with the root, so
+    /// `is_absolute` and [`has_root`] are equivalent.
+    ///
+    /// * On Windows, a path is absolute if it has a prefix and starts with the
+    /// root: `c:\windows` is absolute, while `c:temp` and `\temp` are not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert!(!Utf8Path::new("foo.txt").is_absolute());
+    /// ```
+    ///
+    /// [`has_root`]: Utf8Path::has_root
+    pub fn is_absolute(&self) -> bool {
+        self.0.is_absolute()
+    }
+
+    /// Returns `true` if the `Utf8Path` is relative, i.e., not absolute.
+    ///
+    /// See [`is_absolute`]'s documentation for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert!(Utf8Path::new("foo.txt").is_relative());
+    /// ```
+    ///
+    /// [`is_absolute`]: Utf8Path::is_absolute
+    pub fn is_relative(&self) -> bool {
+        self.0.is_relative()
+    }
+
+    /// Returns `true` if the `Utf8Path` has a root.
+    ///
+    /// * On Unix, a path has a root if it begins with `/`.
+    ///
+    /// * On Windows, a path has a root if it:
+    ///     * has no prefix and begins with a separator, e.g., `\windows`
+    ///     * has a prefix followed by a separator, e.g., `c:\windows` but not `c:windows`
+    ///     * has any non-disk prefix, e.g., `\\server\share`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert!(Utf8Path::new("/etc/passwd").has_root());
+    /// ```
+    pub fn has_root(&self) -> bool {
+        self.0.has_root()
+    }
+
+    /// Returns the `Path` without its final component, if there is one.
+    ///
+    /// Returns [`None`] if the path terminates in a root or prefix.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/foo/bar");
+    /// let parent = path.parent().unwrap();
+    /// assert_eq!(parent, Utf8Path::new("/foo"));
+    ///
+    /// let grand_parent = parent.parent().unwrap();
+    /// assert_eq!(grand_parent, Utf8Path::new("/"));
+    /// assert_eq!(grand_parent.parent(), None);
+    /// ```
+    pub fn parent(&self) -> Option<&Utf8Path> {
+        self.0.parent().map(|path| {
+            // SAFETY: self is valid UTF-8, so parent is valid UTF-8 as well
+            unsafe { Utf8Path::assume_utf8(path) }
+        })
+    }
+
+    /// Produces an iterator over `Utf8Path` and its ancestors.
+    ///
+    /// The iterator will yield the `Utf8Path` that is returned if the [`parent`] method is used zero
+    /// or more times. That means, the iterator will yield `&self`, `&self.parent().unwrap()`,
+    /// `&self.parent().unwrap().parent().unwrap()` and so on. If the [`parent`] method returns
+    /// [`None`], the iterator will do likewise. The iterator will always yield at least one value,
+    /// namely `&self`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let mut ancestors = Utf8Path::new("/foo/bar").ancestors();
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo/bar")));
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/foo")));
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("/")));
+    /// assert_eq!(ancestors.next(), None);
+    ///
+    /// let mut ancestors = Utf8Path::new("../foo/bar").ancestors();
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo/bar")));
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("../foo")));
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("..")));
+    /// assert_eq!(ancestors.next(), Some(Utf8Path::new("")));
+    /// assert_eq!(ancestors.next(), None);
+    /// ```
+    ///
+    /// [`parent`]: Utf8Path::parent
+    pub fn ancestors(&self) -> Utf8Ancestors<'_> {
+        Utf8Ancestors(self.0.ancestors())
+    }
+
+    /// Returns the final component of the `Utf8Path`, if there is one.
+    ///
+    /// If the path is a normal file, this is the file name. If it's the path of a directory, this
+    /// is the directory name.
+    ///
+    /// Returns [`None`] if the path terminates in `..`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert_eq!(Some("bin"), Utf8Path::new("/usr/bin/").file_name());
+    /// assert_eq!(Some("foo.txt"), Utf8Path::new("tmp/foo.txt").file_name());
+    /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.").file_name());
+    /// assert_eq!(Some("foo.txt"), Utf8Path::new("foo.txt/.//").file_name());
+    /// assert_eq!(None, Utf8Path::new("foo.txt/..").file_name());
+    /// assert_eq!(None, Utf8Path::new("/").file_name());
+    /// ```
+    pub fn file_name(&self) -> Option<&str> {
+        self.0.file_name().map(|s| {
+            // SAFETY: self is valid UTF-8, so file_name is valid UTF-8 as well
+            unsafe { assume_utf8(s) }
+        })
+    }
+
+    /// Returns a path that, when joined onto `base`, yields `self`.
+    ///
+    /// # Errors
+    ///
+    /// If `base` is not a prefix of `self` (i.e., [`starts_with`]
+    /// returns `false`), returns [`Err`].
+    ///
+    /// [`starts_with`]: Utf8Path::starts_with
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let path = Utf8Path::new("/test/haha/foo.txt");
+    ///
+    /// assert_eq!(path.strip_prefix("/"), Ok(Utf8Path::new("test/haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test"), Ok(Utf8Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/"), Ok(Utf8Path::new("haha/foo.txt")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt"), Ok(Utf8Path::new("")));
+    /// assert_eq!(path.strip_prefix("/test/haha/foo.txt/"), Ok(Utf8Path::new("")));
+    ///
+    /// assert!(path.strip_prefix("test").is_err());
+    /// assert!(path.strip_prefix("/haha").is_err());
+    ///
+    /// let prefix = Utf8PathBuf::from("/test/");
+    /// assert_eq!(path.strip_prefix(prefix), Ok(Utf8Path::new("haha/foo.txt")));
+    /// ```
+    pub fn strip_prefix(&self, base: impl AsRef<Path>) -> Result<&Utf8Path, StripPrefixError> {
+        self.0.strip_prefix(base).map(|path| {
+            // SAFETY: self is valid UTF-8, and strip_prefix returns a part of self (or an empty
+            // string), so it is valid UTF-8 as well.
+            unsafe { Utf8Path::assume_utf8(path) }
+        })
+    }
+
+    /// Determines whether `base` is a prefix of `self`.
+    ///
+    /// Only considers whole path components to match.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/etc/passwd");
+    ///
+    /// assert!(path.starts_with("/etc"));
+    /// assert!(path.starts_with("/etc/"));
+    /// assert!(path.starts_with("/etc/passwd"));
+    /// assert!(path.starts_with("/etc/passwd/")); // extra slash is okay
+    /// assert!(path.starts_with("/etc/passwd///")); // multiple extra slashes are okay
+    ///
+    /// assert!(!path.starts_with("/e"));
+    /// assert!(!path.starts_with("/etc/passwd.txt"));
+    ///
+    /// assert!(!Utf8Path::new("/etc/foo.rs").starts_with("/etc/foo"));
+    /// ```
+    pub fn starts_with(&self, base: impl AsRef<Path>) -> bool {
+        self.0.starts_with(base)
+    }
+
+    /// Determines whether `child` is a suffix of `self`.
+    ///
+    /// Only considers whole path components to match.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/etc/resolv.conf");
+    ///
+    /// assert!(path.ends_with("resolv.conf"));
+    /// assert!(path.ends_with("etc/resolv.conf"));
+    /// assert!(path.ends_with("/etc/resolv.conf"));
+    ///
+    /// assert!(!path.ends_with("/resolv.conf"));
+    /// assert!(!path.ends_with("conf")); // use .extension() instead
+    /// ```
+    pub fn ends_with(&self, base: impl AsRef<Path>) -> bool {
+        self.0.ends_with(base)
+    }
+
+    /// Extracts the stem (non-extension) portion of [`self.file_name`].
+    ///
+    /// [`self.file_name`]: Utf8Path::file_name
+    ///
+    /// The stem is:
+    ///
+    /// * [`None`], if there is no file name;
+    /// * The entire file name if there is no embedded `.`;
+    /// * The entire file name if the file name begins with `.` and has no other `.`s within;
+    /// * Otherwise, the portion of the file name before the final `.`
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert_eq!("foo", Utf8Path::new("foo.rs").file_stem().unwrap());
+    /// assert_eq!("foo.tar", Utf8Path::new("foo.tar.gz").file_stem().unwrap());
+    /// ```
+    pub fn file_stem(&self) -> Option<&str> {
+        self.0.file_stem().map(|s| {
+            // SAFETY: self is valid UTF-8, so file_stem is valid UTF-8 as well
+            unsafe { assume_utf8(s) }
+        })
+    }
+
+    /// Extracts the extension of [`self.file_name`], if possible.
+    ///
+    /// The extension is:
+    ///
+    /// * [`None`], if there is no file name;
+    /// * [`None`], if there is no embedded `.`;
+    /// * [`None`], if the file name begins with `.` and has no other `.`s within;
+    /// * Otherwise, the portion of the file name after the final `.`
+    ///
+    /// [`self.file_name`]: Utf8Path::file_name
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// assert_eq!("rs", Utf8Path::new("foo.rs").extension().unwrap());
+    /// assert_eq!("gz", Utf8Path::new("foo.tar.gz").extension().unwrap());
+    /// ```
+    pub fn extension(&self) -> Option<&str> {
+        self.0.extension().map(|s| {
+            // SAFETY: self is valid UTF-8, so extension is valid UTF-8 as well
+            unsafe { assume_utf8(s) }
+        })
+    }
+
+    /// Creates an owned [`Utf8PathBuf`] with `path` adjoined to `self`.
+    ///
+    /// See [`Utf8PathBuf::push`] for more details on what it means to adjoin a path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// assert_eq!(Utf8Path::new("/etc").join("passwd"), Utf8PathBuf::from("/etc/passwd"));
+    /// ```
+    pub fn join(&self, path: impl AsRef<Utf8Path>) -> Utf8PathBuf {
+        Utf8PathBuf(self.0.join(&path.as_ref().0))
+    }
+
+    /// Creates an owned [`PathBuf`] with `path` adjoined to `self`.
+    ///
+    /// See [`PathBuf::push`] for more details on what it means to adjoin a path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    /// use std::path::PathBuf;
+    ///
+    /// assert_eq!(Utf8Path::new("/etc").join_os("passwd"), PathBuf::from("/etc/passwd"));
+    /// ```
+    pub fn join_os(&self, path: impl AsRef<Path>) -> PathBuf {
+        self.0.join(path)
+    }
+
+    /// Creates an owned [`Utf8PathBuf`] like `self` but with the given file name.
+    ///
+    /// See [`Utf8PathBuf::set_file_name`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let path = Utf8Path::new("/tmp/foo.txt");
+    /// assert_eq!(path.with_file_name("bar.txt"), Utf8PathBuf::from("/tmp/bar.txt"));
+    ///
+    /// let path = Utf8Path::new("/tmp");
+    /// assert_eq!(path.with_file_name("var"), Utf8PathBuf::from("/var"));
+    /// ```
+    pub fn with_file_name(&self, file_name: impl AsRef<str>) -> Utf8PathBuf {
+        Utf8PathBuf(self.0.with_file_name(file_name.as_ref()))
+    }
+
+    /// Creates an owned [`Utf8PathBuf`] like `self` but with the given extension.
+    ///
+    /// See [`Utf8PathBuf::set_extension`] for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let path = Utf8Path::new("foo.rs");
+    /// assert_eq!(path.with_extension("txt"), Utf8PathBuf::from("foo.txt"));
+    ///
+    /// let path = Utf8Path::new("foo.tar.gz");
+    /// assert_eq!(path.with_extension(""), Utf8PathBuf::from("foo.tar"));
+    /// assert_eq!(path.with_extension("xz"), Utf8PathBuf::from("foo.tar.xz"));
+    /// assert_eq!(path.with_extension("").with_extension("txt"), Utf8PathBuf::from("foo.txt"));
+    /// ```
+    pub fn with_extension(&self, extension: impl AsRef<str>) -> Utf8PathBuf {
+        Utf8PathBuf(self.0.with_extension(extension.as_ref()))
+    }
+
+    /// Produces an iterator over the [`Utf8Component`]s of the path.
+    ///
+    /// When parsing the path, there is a small amount of normalization:
+    ///
+    /// * Repeated separators are ignored, so `a/b` and `a//b` both have
+    ///   `a` and `b` as components.
+    ///
+    /// * Occurrences of `.` are normalized away, except if they are at the
+    ///   beginning of the path. For example, `a/./b`, `a/b/`, `a/b/.` and
+    ///   `a/b` all have `a` and `b` as components, but `./a/b` starts with
+    ///   an additional [`CurDir`] component.
+    ///
+    /// * A trailing slash is normalized away, `/a/b` and `/a/b/` are equivalent.
+    ///
+    /// Note that no other normalization takes place; in particular, `a/c`
+    /// and `a/b/../c` are distinct, to account for the possibility that `b`
+    /// is a symbolic link (so its parent isn't `a`).
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::{Utf8Component, Utf8Path};
+    ///
+    /// let mut components = Utf8Path::new("/tmp/foo.txt").components();
+    ///
+    /// assert_eq!(components.next(), Some(Utf8Component::RootDir));
+    /// assert_eq!(components.next(), Some(Utf8Component::Normal("tmp")));
+    /// assert_eq!(components.next(), Some(Utf8Component::Normal("foo.txt")));
+    /// assert_eq!(components.next(), None)
+    /// ```
+    ///
+    /// [`CurDir`]: Utf8Component::CurDir
+    pub fn components(&self) -> Utf8Components {
+        Utf8Components(self.0.components())
+    }
+
+    /// Produces an iterator over the path's components viewed as [`str`]
+    /// slices.
+    ///
+    /// For more information about the particulars of how the path is separated
+    /// into components, see [`components`].
+    ///
+    /// [`components`]: Utf8Path::components
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let mut it = Utf8Path::new("/tmp/foo.txt").iter();
+    /// assert_eq!(it.next(), Some(std::path::MAIN_SEPARATOR.to_string().as_str()));
+    /// assert_eq!(it.next(), Some("tmp"));
+    /// assert_eq!(it.next(), Some("foo.txt"));
+    /// assert_eq!(it.next(), None)
+    /// ```
+    pub fn iter(&self) -> Iter<'_> {
+        Iter {
+            inner: self.components(),
+        }
+    }
+
+    /// Queries the file system to get information about a file, directory, etc.
+    ///
+    /// This function will traverse symbolic links to query information about the
+    /// destination file.
+    ///
+    /// This is an alias to [`fs::metadata`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/Minas/tirith");
+    /// let metadata = path.metadata().expect("metadata call failed");
+    /// println!("{:?}", metadata.file_type());
+    /// ```
+    pub fn metadata(&self) -> io::Result<fs::Metadata> {
+        self.0.metadata()
+    }
+
+    /// Queries the metadata about a file without following symlinks.
+    ///
+    /// This is an alias to [`fs::symlink_metadata`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/Minas/tirith");
+    /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
+    /// println!("{:?}", metadata.file_type());
+    /// ```
+    pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
+        self.0.symlink_metadata()
+    }
+
+    /// Returns the canonical, absolute form of the path with all intermediate
+    /// components normalized and symbolic links resolved.
+    ///
+    /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not
+    /// be. For a version that returns a [`Utf8PathBuf`], see
+    /// [`canonicalize_utf8`](Self::canonicalize_utf8).
+    ///
+    /// This is an alias to [`fs::canonicalize`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    /// use std::path::PathBuf;
+    ///
+    /// let path = Utf8Path::new("/foo/test/../test/bar.rs");
+    /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
+    /// ```
+    pub fn canonicalize(&self) -> io::Result<PathBuf> {
+        self.0.canonicalize()
+    }
+
+    /// Returns the canonical, absolute form of the path with all intermediate
+    /// components normalized and symbolic links resolved.
+    ///
+    /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a
+    /// version that does not attempt to do this conversion, see
+    /// [`canonicalize`](Self::canonicalize).
+    ///
+    /// # Errors
+    ///
+    /// The I/O operation may return an error: see the [`fs::canonicalize`]
+    /// documentation for more.
+    ///
+    /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the
+    /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a
+    /// [`FromPathBufError`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::{Utf8Path, Utf8PathBuf};
+    ///
+    /// let path = Utf8Path::new("/foo/test/../test/bar.rs");
+    /// assert_eq!(path.canonicalize_utf8().unwrap(), Utf8PathBuf::from("/foo/test/bar.rs"));
+    /// ```
+    pub fn canonicalize_utf8(&self) -> io::Result<Utf8PathBuf> {
+        self.canonicalize().and_then(|path| {
+            path.try_into()
+                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
+        })
+    }
+
+    /// Reads a symbolic link, returning the file that the link points to.
+    ///
+    /// This returns a [`PathBuf`] because even if a symlink is valid Unicode, its target may not
+    /// be. For a version that returns a [`Utf8PathBuf`], see
+    /// [`read_link_utf8`](Self::read_link_utf8).
+    ///
+    /// This is an alias to [`fs::read_link`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/laputa/sky_castle.rs");
+    /// let path_link = path.read_link().expect("read_link call failed");
+    /// ```
+    pub fn read_link(&self) -> io::Result<PathBuf> {
+        self.0.read_link()
+    }
+
+    /// Reads a symbolic link, returning the file that the link points to.
+    ///
+    /// This method attempts to convert the resulting [`PathBuf`] into a [`Utf8PathBuf`]. For a
+    /// version that does not attempt to do this conversion, see [`read_link`](Self::read_link).
+    ///
+    /// # Errors
+    ///
+    /// The I/O operation may return an error: see the [`fs::read_link`]
+    /// documentation for more.
+    ///
+    /// If the resulting path is not UTF-8, an [`io::Error`] is returned with the
+    /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a
+    /// [`FromPathBufError`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/laputa/sky_castle.rs");
+    /// let path_link = path.read_link_utf8().expect("read_link call failed");
+    /// ```
+    pub fn read_link_utf8(&self) -> io::Result<Utf8PathBuf> {
+        self.read_link().and_then(|path| {
+            path.try_into()
+                .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
+        })
+    }
+
+    /// Returns an iterator over the entries within a directory.
+    ///
+    /// The iterator will yield instances of [`io::Result`]`<`[`fs::DirEntry`]`>`. New
+    /// errors may be encountered after an iterator is initially constructed.
+    ///
+    /// This is an alias to [`fs::read_dir`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/laputa");
+    /// for entry in path.read_dir().expect("read_dir call failed") {
+    ///     if let Ok(entry) = entry {
+    ///         println!("{:?}", entry.path());
+    ///     }
+    /// }
+    /// ```
+    pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
+        self.0.read_dir()
+    }
+
+    /// Returns an iterator over the entries within a directory.
+    ///
+    /// The iterator will yield instances of [`io::Result`]`<`[`Utf8DirEntry`]`>`. New
+    /// errors may be encountered after an iterator is initially constructed.
+    ///
+    /// # Errors
+    ///
+    /// The I/O operation may return an error: see the [`fs::read_dir`]
+    /// documentation for more.
+    ///
+    /// If a directory entry is not UTF-8, an [`io::Error`] is returned with the
+    /// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a
+    /// [`FromPathBufError`].
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("/laputa");
+    /// for entry in path.read_dir_utf8().expect("read_dir call failed") {
+    ///     if let Ok(entry) = entry {
+    ///         println!("{}", entry.path());
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    pub fn read_dir_utf8(&self) -> io::Result<ReadDirUtf8> {
+        self.0.read_dir().map(|inner| ReadDirUtf8 { inner })
+    }
+
+    /// Returns `true` if the path points at an existing entity.
+    ///
+    /// This function will traverse symbolic links to query information about the
+    /// destination file. In case of broken symbolic links this will return `false`.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return `false`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    /// assert!(!Utf8Path::new("does_not_exist.txt").exists());
+    /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [`fs::metadata`].
+    pub fn exists(&self) -> bool {
+        self.0.exists()
+    }
+
+    /// Returns `true` if the path exists on disk and is pointing at a regular file.
+    ///
+    /// This function will traverse symbolic links to query information about the
+    /// destination file. In case of broken symbolic links this will return `false`.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return `false`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    /// assert_eq!(Utf8Path::new("./is_a_directory/").is_file(), false);
+    /// assert_eq!(Utf8Path::new("a_file.txt").is_file(), true);
+    /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
+    /// [`fs::Metadata::is_file`] if it was [`Ok`].
+    ///
+    /// When the goal is simply to read from (or write to) the source, the most
+    /// reliable way to test the source can be read (or written to) is to open
+    /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
+    /// a Unix-like system for example. See [`fs::File::open`] or
+    /// [`fs::OpenOptions::open`] for more information.
+    pub fn is_file(&self) -> bool {
+        self.0.is_file()
+    }
+
+    /// Returns `true` if the path exists on disk and is pointing at a directory.
+    ///
+    /// This function will traverse symbolic links to query information about the
+    /// destination file. In case of broken symbolic links this will return `false`.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return `false`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    /// assert_eq!(Utf8Path::new("./is_a_directory/").is_dir(), true);
+    /// assert_eq!(Utf8Path::new("a_file.txt").is_dir(), false);
+    /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
+    /// [`fs::Metadata::is_dir`] if it was [`Ok`].
+    pub fn is_dir(&self) -> bool {
+        self.0.is_dir()
+    }
+
+    /// Returns `true` if the path exists on disk and is pointing at a symbolic link.
+    ///
+    /// This function will not traverse symbolic links.
+    /// In case of a broken symbolic link this will also return true.
+    ///
+    /// If you cannot access the directory containing the file, e.g., because of a
+    /// permission error, this will return false.
+    ///
+    /// # Examples
+    ///
+    #[cfg_attr(unix, doc = "```no_run")]
+    #[cfg_attr(not(unix), doc = "```ignore")]
+    /// use camino::Utf8Path;
+    /// use std::os::unix::fs::symlink;
+    ///
+    /// let link_path = Utf8Path::new("link");
+    /// symlink("/origin_does_not_exist/", link_path).unwrap();
+    /// assert_eq!(link_path.is_symlink(), true);
+    /// assert_eq!(link_path.exists(), false);
+    /// ```
+    ///
+    /// # See Also
+    ///
+    /// This is a convenience function that coerces errors to false. If you want to
+    /// check errors, call [`Utf8Path::symlink_metadata`] and handle its [`Result`]. Then call
+    /// [`fs::Metadata::is_symlink`] if it was [`Ok`].
+    #[must_use]
+    pub fn is_symlink(&self) -> bool {
+        self.symlink_metadata()
+            .map(|m| m.file_type().is_symlink())
+            .unwrap_or(false)
+    }
+
+    /// Converts a `Box<Utf8Path>` into a [`Utf8PathBuf`] without copying or allocating.
+    pub fn into_path_buf(self: Box<Utf8Path>) -> Utf8PathBuf {
+        let ptr = Box::into_raw(self) as *mut Path;
+        // SAFETY:
+        // * self is valid UTF-8
+        // * ptr was constructed by consuming self so it represents an owned path.
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from a *mut Utf8Path to a
+        //   *mut Path is valid.
+        let boxed_path = unsafe { Box::from_raw(ptr) };
+        Utf8PathBuf(boxed_path.into_path_buf())
+    }
+
+    // invariant: Path must be guaranteed to be utf-8 data
+    unsafe fn assume_utf8(path: &Path) -> &Utf8Path {
+        // SAFETY: Utf8Path is marked as #[repr(transparent)] so the conversion from a
+        // *const Path to a *const Utf8Path is valid.
+        &*(path as *const Path as *const Utf8Path)
+    }
+}
+
+impl Clone for Box<Utf8Path> {
+    fn clone(&self) -> Self {
+        let boxed: Box<Path> = self.0.into();
+        let ptr = Box::into_raw(boxed) as *mut Utf8Path;
+        // SAFETY:
+        // * self is valid UTF-8
+        // * ptr was created by consuming a Box<Path> so it represents an rced pointer
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *mut Path to
+        //   *mut Utf8Path is valid
+        unsafe { Box::from_raw(ptr) }
+    }
+}
+
+impl fmt::Display for Utf8Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
+impl fmt::Debug for Utf8Path {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_str(), f)
+    }
+}
+
+/// An iterator over [`Utf8Path`] and its ancestors.
+///
+/// This `struct` is created by the [`ancestors`] method on [`Utf8Path`].
+/// See its documentation for more.
+///
+/// # Examples
+///
+/// ```
+/// use camino::Utf8Path;
+///
+/// let path = Utf8Path::new("/foo/bar");
+///
+/// for ancestor in path.ancestors() {
+///     println!("{}", ancestor);
+/// }
+/// ```
+///
+/// [`ancestors`]: Utf8Path::ancestors
+#[derive(Copy, Clone)]
+#[repr(transparent)]
+pub struct Utf8Ancestors<'a>(Ancestors<'a>);
+
+impl<'a> fmt::Debug for Utf8Ancestors<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl<'a> Iterator for Utf8Ancestors<'a> {
+    type Item = &'a Utf8Path;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next().map(|path| {
+            // SAFETY: Utf8Ancestors was constructed from a Utf8Path, so it is guaranteed to
+            // be valid UTF-8
+            unsafe { Utf8Path::assume_utf8(path) }
+        })
+    }
+}
+
+impl<'a> FusedIterator for Utf8Ancestors<'a> {}
+
+/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`].
+///
+/// This `struct` is created by the [`components`] method on [`Utf8Path`].
+/// See its documentation for more.
+///
+/// # Examples
+///
+/// ```
+/// use camino::Utf8Path;
+///
+/// let path = Utf8Path::new("/tmp/foo/bar.txt");
+///
+/// for component in path.components() {
+///     println!("{:?}", component);
+/// }
+/// ```
+///
+/// [`components`]: Utf8Path::components
+#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
+pub struct Utf8Components<'a>(Components<'a>);
+
+impl<'a> Utf8Components<'a> {
+    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let mut components = Utf8Path::new("/tmp/foo/bar.txt").components();
+    /// components.next();
+    /// components.next();
+    ///
+    /// assert_eq!(Utf8Path::new("foo/bar.txt"), components.as_path());
+    /// ```
+    pub fn as_path(&self) -> &'a Utf8Path {
+        // SAFETY: Utf8Components was constructed from a Utf8Path, so it is guaranteed to be valid
+        // UTF-8
+        unsafe { Utf8Path::assume_utf8(self.0.as_path()) }
+    }
+}
+
+impl<'a> Iterator for Utf8Components<'a> {
+    type Item = Utf8Component<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next().map(|component| {
+            // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be
+            // valid UTF-8
+            unsafe { Utf8Component::new(component) }
+        })
+    }
+}
+
+impl<'a> FusedIterator for Utf8Components<'a> {}
+
+impl<'a> DoubleEndedIterator for Utf8Components<'a> {
+    fn next_back(&mut self) -> Option<Self::Item> {
+        self.0.next_back().map(|component| {
+            // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be
+            // valid UTF-8
+            unsafe { Utf8Component::new(component) }
+        })
+    }
+}
+
+impl<'a> fmt::Debug for Utf8Components<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl AsRef<Utf8Path> for Utf8Components<'_> {
+    fn as_ref(&self) -> &Utf8Path {
+        self.as_path()
+    }
+}
+
+impl AsRef<Path> for Utf8Components<'_> {
+    fn as_ref(&self) -> &Path {
+        self.as_path().as_ref()
+    }
+}
+
+impl AsRef<str> for Utf8Components<'_> {
+    fn as_ref(&self) -> &str {
+        self.as_path().as_ref()
+    }
+}
+
+impl AsRef<OsStr> for Utf8Components<'_> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_path().as_os_str()
+    }
+}
+
+/// An iterator over the [`Utf8Component`]s of a [`Utf8Path`], as [`str`] slices.
+///
+/// This `struct` is created by the [`iter`] method on [`Utf8Path`].
+/// See its documentation for more.
+///
+/// [`iter`]: Utf8Path::iter
+#[derive(Clone)]
+pub struct Iter<'a> {
+    inner: Utf8Components<'a>,
+}
+
+impl fmt::Debug for Iter<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        struct DebugHelper<'a>(&'a Utf8Path);
+
+        impl fmt::Debug for DebugHelper<'_> {
+            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                f.debug_list().entries(self.0.iter()).finish()
+            }
+        }
+
+        f.debug_tuple("Iter")
+            .field(&DebugHelper(self.as_path()))
+            .finish()
+    }
+}
+
+impl<'a> Iter<'a> {
+    /// Extracts a slice corresponding to the portion of the path remaining for iteration.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let mut iter = Utf8Path::new("/tmp/foo/bar.txt").iter();
+    /// iter.next();
+    /// iter.next();
+    ///
+    /// assert_eq!(Utf8Path::new("foo/bar.txt"), iter.as_path());
+    /// ```
+    pub fn as_path(&self) -> &'a Utf8Path {
+        self.inner.as_path()
+    }
+}
+
+impl AsRef<Utf8Path> for Iter<'_> {
+    fn as_ref(&self) -> &Utf8Path {
+        self.as_path()
+    }
+}
+
+impl AsRef<Path> for Iter<'_> {
+    fn as_ref(&self) -> &Path {
+        self.as_path().as_ref()
+    }
+}
+
+impl AsRef<str> for Iter<'_> {
+    fn as_ref(&self) -> &str {
+        self.as_path().as_ref()
+    }
+}
+
+impl AsRef<OsStr> for Iter<'_> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_path().as_os_str()
+    }
+}
+
+impl<'a> Iterator for Iter<'a> {
+    type Item = &'a str;
+
+    fn next(&mut self) -> Option<&'a str> {
+        self.inner.next().map(|component| component.as_str())
+    }
+}
+
+impl<'a> DoubleEndedIterator for Iter<'a> {
+    fn next_back(&mut self) -> Option<&'a str> {
+        self.inner.next_back().map(|component| component.as_str())
+    }
+}
+
+impl FusedIterator for Iter<'_> {}
+
+/// A single component of a path.
+///
+/// A `Utf8Component` roughly corresponds to a substring between path separators
+/// (`/` or `\`).
+///
+/// This `enum` is created by iterating over [`Utf8Components`], which in turn is
+/// created by the [`components`](Utf8Path::components) method on [`Utf8Path`].
+///
+/// # Examples
+///
+/// ```rust
+/// use camino::{Utf8Component, Utf8Path};
+///
+/// let path = Utf8Path::new("/tmp/foo/bar.txt");
+/// let components = path.components().collect::<Vec<_>>();
+/// assert_eq!(&components, &[
+///     Utf8Component::RootDir,
+///     Utf8Component::Normal("tmp"),
+///     Utf8Component::Normal("foo"),
+///     Utf8Component::Normal("bar.txt"),
+/// ]);
+/// ```
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)]
+pub enum Utf8Component<'a> {
+    /// A Windows path prefix, e.g., `C:` or `\\server\share`.
+    ///
+    /// There is a large variety of prefix types, see [`Utf8Prefix`]'s documentation
+    /// for more.
+    ///
+    /// Does not occur on Unix.
+    Prefix(Utf8PrefixComponent<'a>),
+
+    /// The root directory component, appears after any prefix and before anything else.
+    ///
+    /// It represents a separator that designates that a path starts from root.
+    RootDir,
+
+    /// A reference to the current directory, i.e., `.`.
+    CurDir,
+
+    /// A reference to the parent directory, i.e., `..`.
+    ParentDir,
+
+    /// A normal component, e.g., `a` and `b` in `a/b`.
+    ///
+    /// This variant is the most common one, it represents references to files
+    /// or directories.
+    Normal(&'a str),
+}
+
+impl<'a> Utf8Component<'a> {
+    unsafe fn new(component: Component<'a>) -> Utf8Component<'a> {
+        match component {
+            Component::Prefix(prefix) => Utf8Component::Prefix(Utf8PrefixComponent(prefix)),
+            Component::RootDir => Utf8Component::RootDir,
+            Component::CurDir => Utf8Component::CurDir,
+            Component::ParentDir => Utf8Component::ParentDir,
+            Component::Normal(s) => Utf8Component::Normal(assume_utf8(s)),
+        }
+    }
+
+    /// Extracts the underlying [`str`] slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("./tmp/foo/bar.txt");
+    /// let components: Vec<_> = path.components().map(|comp| comp.as_str()).collect();
+    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
+    /// ```
+    pub fn as_str(&self) -> &'a str {
+        // SAFETY: Utf8Component was constructed from a Utf8Path, so it is guaranteed to be
+        // valid UTF-8
+        unsafe { assume_utf8(self.as_os_str()) }
+    }
+
+    /// Extracts the underlying [`OsStr`] slice.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// let path = Utf8Path::new("./tmp/foo/bar.txt");
+    /// let components: Vec<_> = path.components().map(|comp| comp.as_os_str()).collect();
+    /// assert_eq!(&components, &[".", "tmp", "foo", "bar.txt"]);
+    /// ```
+    pub fn as_os_str(&self) -> &'a OsStr {
+        match *self {
+            Utf8Component::Prefix(prefix) => prefix.as_os_str(),
+            Utf8Component::RootDir => Component::RootDir.as_os_str(),
+            Utf8Component::CurDir => Component::CurDir.as_os_str(),
+            Utf8Component::ParentDir => Component::ParentDir.as_os_str(),
+            Utf8Component::Normal(s) => OsStr::new(s),
+        }
+    }
+}
+
+impl<'a> fmt::Debug for Utf8Component<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(self.as_os_str(), f)
+    }
+}
+
+impl<'a> fmt::Display for Utf8Component<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
+impl AsRef<Utf8Path> for Utf8Component<'_> {
+    fn as_ref(&self) -> &Utf8Path {
+        self.as_str().as_ref()
+    }
+}
+
+impl AsRef<Path> for Utf8Component<'_> {
+    fn as_ref(&self) -> &Path {
+        self.as_os_str().as_ref()
+    }
+}
+
+impl AsRef<str> for Utf8Component<'_> {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+
+impl AsRef<OsStr> for Utf8Component<'_> {
+    fn as_ref(&self) -> &OsStr {
+        self.as_os_str()
+    }
+}
+
+/// Windows path prefixes, e.g., `C:` or `\\server\share`.
+///
+/// Windows uses a variety of path prefix styles, including references to drive
+/// volumes (like `C:`), network shared folders (like `\\server\share`), and
+/// others. In addition, some path prefixes are "verbatim" (i.e., prefixed with
+/// `\\?\`), in which case `/` is *not* treated as a separator and essentially
+/// no normalization is performed.
+///
+/// # Examples
+///
+/// ```
+/// use camino::{Utf8Component, Utf8Path, Utf8Prefix};
+/// use camino::Utf8Prefix::*;
+///
+/// fn get_path_prefix(s: &str) -> Utf8Prefix {
+///     let path = Utf8Path::new(s);
+///     match path.components().next().unwrap() {
+///         Utf8Component::Prefix(prefix_component) => prefix_component.kind(),
+///         _ => panic!(),
+///     }
+/// }
+///
+/// # if cfg!(windows) {
+/// assert_eq!(Verbatim("pictures"), get_path_prefix(r"\\?\pictures\kittens"));
+/// assert_eq!(VerbatimUNC("server", "share"), get_path_prefix(r"\\?\UNC\server\share"));
+/// assert_eq!(VerbatimDisk(b'C'), get_path_prefix(r"\\?\c:\"));
+/// assert_eq!(DeviceNS("BrainInterface"), get_path_prefix(r"\\.\BrainInterface"));
+/// assert_eq!(UNC("server", "share"), get_path_prefix(r"\\server\share"));
+/// assert_eq!(Disk(b'C'), get_path_prefix(r"C:\Users\Rust\Pictures\Ferris"));
+/// # }
+/// ```
+#[derive(Copy, Clone, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
+pub enum Utf8Prefix<'a> {
+    /// Verbatim prefix, e.g., `\\?\cat_pics`.
+    ///
+    /// Verbatim prefixes consist of `\\?\` immediately followed by the given
+    /// component.
+    Verbatim(&'a str),
+
+    /// Verbatim prefix using Windows' _**U**niform **N**aming **C**onvention_,
+    /// e.g., `\\?\UNC\server\share`.
+    ///
+    /// Verbatim UNC prefixes consist of `\\?\UNC\` immediately followed by the
+    /// server's hostname and a share name.
+    VerbatimUNC(&'a str, &'a str),
+
+    /// Verbatim disk prefix, e.g., `\\?\C:`.
+    ///
+    /// Verbatim disk prefixes consist of `\\?\` immediately followed by the
+    /// drive letter and `:`.
+    VerbatimDisk(u8),
+
+    /// Device namespace prefix, e.g., `\\.\COM42`.
+    ///
+    /// Device namespace prefixes consist of `\\.\` immediately followed by the
+    /// device name.
+    DeviceNS(&'a str),
+
+    /// Prefix using Windows' _**U**niform **N**aming **C**onvention_, e.g.
+    /// `\\server\share`.
+    ///
+    /// UNC prefixes consist of the server's hostname and a share name.
+    UNC(&'a str, &'a str),
+
+    /// Prefix `C:` for the given disk drive.
+    Disk(u8),
+}
+
+impl<'a> Utf8Prefix<'a> {
+    /// Determines if the prefix is verbatim, i.e., begins with `\\?\`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Prefix::*;
+    ///
+    /// assert!(Verbatim("pictures").is_verbatim());
+    /// assert!(VerbatimUNC("server", "share").is_verbatim());
+    /// assert!(VerbatimDisk(b'C').is_verbatim());
+    /// assert!(!DeviceNS("BrainInterface").is_verbatim());
+    /// assert!(!UNC("server", "share").is_verbatim());
+    /// assert!(!Disk(b'C').is_verbatim());
+    /// ```
+    pub fn is_verbatim(&self) -> bool {
+        use Utf8Prefix::*;
+        match self {
+            Verbatim(_) | VerbatimDisk(_) | VerbatimUNC(..) => true,
+            _ => false,
+        }
+    }
+}
+
+/// A structure wrapping a Windows path prefix as well as its unparsed string
+/// representation.
+///
+/// In addition to the parsed [`Utf8Prefix`] information returned by [`kind`],
+/// `Utf8PrefixComponent` also holds the raw and unparsed [`str`] slice,
+/// returned by [`as_str`].
+///
+/// Instances of this `struct` can be obtained by matching against the
+/// [`Prefix` variant] on [`Utf8Component`].
+///
+/// Does not occur on Unix.
+///
+/// # Examples
+///
+/// ```
+/// # if cfg!(windows) {
+/// use camino::{Utf8Component, Utf8Path, Utf8Prefix};
+/// use std::ffi::OsStr;
+///
+/// let path = Utf8Path::new(r"c:\you\later\");
+/// match path.components().next().unwrap() {
+///     Utf8Component::Prefix(prefix_component) => {
+///         assert_eq!(Utf8Prefix::Disk(b'C'), prefix_component.kind());
+///         assert_eq!("c:", prefix_component.as_str());
+///     }
+///     _ => unreachable!(),
+/// }
+/// # }
+/// ```
+///
+/// [`as_str`]: Utf8PrefixComponent::as_str
+/// [`kind`]: Utf8PrefixComponent::kind
+/// [`Prefix` variant]: Utf8Component::Prefix
+#[repr(transparent)]
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd)]
+pub struct Utf8PrefixComponent<'a>(PrefixComponent<'a>);
+
+impl<'a> Utf8PrefixComponent<'a> {
+    /// Returns the parsed prefix data.
+    ///
+    /// See [`Utf8Prefix`]'s documentation for more information on the different
+    /// kinds of prefixes.
+    pub fn kind(&self) -> Utf8Prefix<'a> {
+        // SAFETY for all the below unsafe blocks: the path self was originally constructed from was
+        // UTF-8 so any parts of it are valid UTF-8
+        match self.0.kind() {
+            Prefix::Verbatim(prefix) => Utf8Prefix::Verbatim(unsafe { assume_utf8(prefix) }),
+            Prefix::VerbatimUNC(server, share) => {
+                let server = unsafe { assume_utf8(server) };
+                let share = unsafe { assume_utf8(share) };
+                Utf8Prefix::VerbatimUNC(server, share)
+            }
+            Prefix::VerbatimDisk(drive) => Utf8Prefix::VerbatimDisk(drive),
+            Prefix::DeviceNS(prefix) => Utf8Prefix::DeviceNS(unsafe { assume_utf8(prefix) }),
+            Prefix::UNC(server, share) => {
+                let server = unsafe { assume_utf8(server) };
+                let share = unsafe { assume_utf8(share) };
+                Utf8Prefix::UNC(server, share)
+            }
+            Prefix::Disk(drive) => Utf8Prefix::Disk(drive),
+        }
+    }
+
+    /// Returns the [`str`] slice for this prefix.
+    pub fn as_str(&self) -> &'a str {
+        // SAFETY: Utf8PrefixComponent was constructed from a Utf8Path, so it is guaranteed to be
+        // valid UTF-8
+        unsafe { assume_utf8(self.as_os_str()) }
+    }
+
+    /// Returns the raw [`OsStr`] slice for this prefix.
+    pub fn as_os_str(&self) -> &'a OsStr {
+        self.0.as_os_str()
+    }
+}
+
+impl<'a> fmt::Debug for Utf8PrefixComponent<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Debug::fmt(&self.0, f)
+    }
+}
+
+impl<'a> fmt::Display for Utf8PrefixComponent<'a> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
+// ---
+// read_dir_utf8
+// ---
+
+/// Iterator over the entries in a directory.
+///
+/// This iterator is returned from [`Utf8Path::read_dir_utf8`] and will yield instances of
+/// <code>[io::Result]<[Utf8DirEntry]></code>. Through a [`Utf8 DirEntry`] information like the entry's path
+/// and possibly other metadata can be learned.
+///
+/// The order in which this iterator returns entries is platform and filesystem
+/// dependent.
+///
+/// # Errors
+///
+/// This [`io::Result`] will be an [`Err`] if there's some sort of intermittent
+/// IO error during iteration.
+///
+/// If a directory entry is not UTF-8, an [`io::Error`] is returned with the
+/// [`ErrorKind`](io::ErrorKind) set to `InvalidData` and the payload set to a [`FromPathBufError`].
+#[derive(Debug)]
+pub struct ReadDirUtf8 {
+    inner: fs::ReadDir,
+}
+
+impl Iterator for ReadDirUtf8 {
+    type Item = io::Result<Utf8DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<Utf8DirEntry>> {
+        self.inner
+            .next()
+            .map(|entry| entry.and_then(Utf8DirEntry::new))
+    }
+}
+
+/// Entries returned by the [`ReadDirUtf8`] iterator.
+///
+/// An instance of `Utf8DirEntry` represents an entry inside of a directory on the filesystem. Each
+/// entry can be inspected via methods to learn about the full path or possibly other metadata.
+#[derive(Debug)]
+pub struct Utf8DirEntry {
+    inner: fs::DirEntry,
+    path: Utf8PathBuf,
+}
+
+impl Utf8DirEntry {
+    fn new(inner: fs::DirEntry) -> io::Result<Self> {
+        let path = inner
+            .path()
+            .try_into()
+            .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
+        Ok(Self { inner, path })
+    }
+
+    /// Returns the full path to the file that this entry represents.
+    ///
+    /// The full path is created by joining the original path to `read_dir`
+    /// with the filename of this entry.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use camino::Utf8Path;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     for entry in Utf8Path::new(".").read_dir_utf8()? {
+    ///         let dir = entry?;
+    ///         println!("{}", dir.path());
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    ///
+    /// This prints output like:
+    ///
+    /// ```text
+    /// ./whatever.txt
+    /// ./foo.html
+    /// ./hello_world.rs
+    /// ```
+    ///
+    /// The exact text, of course, depends on what files you have in `.`.
+    #[inline]
+    pub fn path(&self) -> &Utf8Path {
+        &self.path
+    }
+
+    /// Returns the metadata for the file that this entry points at.
+    ///
+    /// This function will not traverse symlinks if this entry points at a symlink. To traverse
+    /// symlinks use [`Utf8Path::metadata`] or [`fs::File::metadata`].
+    ///
+    /// # Platform-specific behavior
+    ///
+    /// On Windows this function is cheap to call (no extra system calls
+    /// needed), but on Unix platforms this function is the equivalent of
+    /// calling `symlink_metadata` on the path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `Utf8DirEntry`.
+    ///             if let Ok(metadata) = entry.metadata() {
+    ///                 // Now let's show our entry's permissions!
+    ///                 println!("{}: {:?}", entry.path(), metadata.permissions());
+    ///             } else {
+    ///                 println!("Couldn't get metadata for {}", entry.path());
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    pub fn metadata(&self) -> io::Result<Metadata> {
+        self.inner.metadata()
+    }
+
+    /// Returns the file type for the file that this entry points at.
+    ///
+    /// This function will not traverse symlinks if this entry points at a
+    /// symlink.
+    ///
+    /// # Platform-specific behavior
+    ///
+    /// On Windows and most Unix platforms this function is free (no extra
+    /// system calls needed), but some Unix platforms may require the equivalent
+    /// call to `symlink_metadata` to learn about the target file type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             if let Ok(file_type) = entry.file_type() {
+    ///                 // Now let's show our entry's file type!
+    ///                 println!("{}: {:?}", entry.path(), file_type);
+    ///             } else {
+    ///                 println!("Couldn't get file type for {}", entry.path());
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    #[inline]
+    pub fn file_type(&self) -> io::Result<fs::FileType> {
+        self.inner.file_type()
+    }
+
+    /// Returns the bare file name of this directory entry without any other
+    /// leading path component.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use camino::Utf8Path;
+    ///
+    /// if let Ok(entries) = Utf8Path::new(".").read_dir_utf8() {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             println!("{}", entry.file_name());
+    ///         }
+    ///     }
+    /// }
+    /// ```
+    pub fn file_name(&self) -> &str {
+        self.path
+            .file_name()
+            .expect("path created through DirEntry must have a filename")
+    }
+
+    /// Returns the original [`fs::DirEntry`] within this [`Utf8DirEntry`].
+    #[inline]
+    pub fn into_inner(self) -> fs::DirEntry {
+        self.inner
+    }
+}
+
+impl From<String> for Utf8PathBuf {
+    fn from(string: String) -> Utf8PathBuf {
+        Utf8PathBuf(string.into())
+    }
+}
+
+impl FromStr for Utf8PathBuf {
+    type Err = Infallible;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        Ok(Utf8PathBuf(s.into()))
+    }
+}
+
+// ---
+// From impls: borrowed -> borrowed
+// ---
+
+impl<'a> From<&'a str> for &'a Utf8Path {
+    fn from(s: &'a str) -> &'a Utf8Path {
+        Utf8Path::new(s)
+    }
+}
+
+// ---
+// From impls: borrowed -> owned
+// ---
+
+impl<T: ?Sized + AsRef<str>> From<&T> for Utf8PathBuf {
+    fn from(s: &T) -> Utf8PathBuf {
+        Utf8PathBuf::from(s.as_ref().to_owned())
+    }
+}
+
+impl<T: ?Sized + AsRef<str>> From<&T> for Box<Utf8Path> {
+    fn from(s: &T) -> Box<Utf8Path> {
+        Utf8PathBuf::from(s).into_boxed_path()
+    }
+}
+
+impl From<&'_ Utf8Path> for Arc<Utf8Path> {
+    fn from(path: &Utf8Path) -> Arc<Utf8Path> {
+        let arc: Arc<Path> = Arc::from(AsRef::<Path>::as_ref(path));
+        let ptr = Arc::into_raw(arc) as *const Utf8Path;
+        // SAFETY:
+        // * path is valid UTF-8
+        // * ptr was created by consuming an Arc<Path> so it represents an arced pointer
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to
+        //   *const Utf8Path is valid
+        unsafe { Arc::from_raw(ptr) }
+    }
+}
+
+impl From<&'_ Utf8Path> for Rc<Utf8Path> {
+    fn from(path: &Utf8Path) -> Rc<Utf8Path> {
+        let rc: Rc<Path> = Rc::from(AsRef::<Path>::as_ref(path));
+        let ptr = Rc::into_raw(rc) as *const Utf8Path;
+        // SAFETY:
+        // * path is valid UTF-8
+        // * ptr was created by consuming an Rc<Path> so it represents an rced pointer
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to
+        //   *const Utf8Path is valid
+        unsafe { Rc::from_raw(ptr) }
+    }
+}
+
+impl<'a> From<&'a Utf8Path> for Cow<'a, Utf8Path> {
+    fn from(path: &'a Utf8Path) -> Cow<'a, Utf8Path> {
+        Cow::Borrowed(path)
+    }
+}
+
+impl From<&'_ Utf8Path> for Box<Path> {
+    fn from(path: &Utf8Path) -> Box<Path> {
+        AsRef::<Path>::as_ref(path).into()
+    }
+}
+
+impl From<&'_ Utf8Path> for Arc<Path> {
+    fn from(path: &Utf8Path) -> Arc<Path> {
+        AsRef::<Path>::as_ref(path).into()
+    }
+}
+
+impl From<&'_ Utf8Path> for Rc<Path> {
+    fn from(path: &Utf8Path) -> Rc<Path> {
+        AsRef::<Path>::as_ref(path).into()
+    }
+}
+
+impl<'a> From<&'a Utf8Path> for Cow<'a, Path> {
+    fn from(path: &'a Utf8Path) -> Cow<'a, Path> {
+        Cow::Borrowed(path.as_ref())
+    }
+}
+
+// ---
+// From impls: owned -> owned
+// ---
+
+impl From<Box<Utf8Path>> for Utf8PathBuf {
+    fn from(path: Box<Utf8Path>) -> Utf8PathBuf {
+        path.into_path_buf()
+    }
+}
+
+impl From<Utf8PathBuf> for Box<Utf8Path> {
+    fn from(path: Utf8PathBuf) -> Box<Utf8Path> {
+        path.into_boxed_path()
+    }
+}
+
+impl<'a> From<Cow<'a, Utf8Path>> for Utf8PathBuf {
+    fn from(path: Cow<'a, Utf8Path>) -> Utf8PathBuf {
+        path.into_owned()
+    }
+}
+
+impl From<Utf8PathBuf> for String {
+    fn from(path: Utf8PathBuf) -> String {
+        path.into_string()
+    }
+}
+
+impl From<Utf8PathBuf> for OsString {
+    fn from(path: Utf8PathBuf) -> OsString {
+        path.into_os_string()
+    }
+}
+
+impl<'a> From<Utf8PathBuf> for Cow<'a, Utf8Path> {
+    fn from(path: Utf8PathBuf) -> Cow<'a, Utf8Path> {
+        Cow::Owned(path)
+    }
+}
+
+impl From<Utf8PathBuf> for Arc<Utf8Path> {
+    fn from(path: Utf8PathBuf) -> Arc<Utf8Path> {
+        let arc: Arc<Path> = Arc::from(path.0);
+        let ptr = Arc::into_raw(arc) as *const Utf8Path;
+        // SAFETY:
+        // * path is valid UTF-8
+        // * ptr was created by consuming an Arc<Path> so it represents an arced pointer
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to
+        //   *const Utf8Path is valid
+        unsafe { Arc::from_raw(ptr) }
+    }
+}
+
+impl From<Utf8PathBuf> for Rc<Utf8Path> {
+    fn from(path: Utf8PathBuf) -> Rc<Utf8Path> {
+        let rc: Rc<Path> = Rc::from(path.0);
+        let ptr = Rc::into_raw(rc) as *const Utf8Path;
+        // SAFETY:
+        // * path is valid UTF-8
+        // * ptr was created by consuming an Rc<Path> so it represents an rced pointer
+        // * Utf8Path is marked as #[repr(transparent)] so the conversion from *const Path to
+        //   *const Utf8Path is valid
+        unsafe { Rc::from_raw(ptr) }
+    }
+}
+
+impl From<Utf8PathBuf> for PathBuf {
+    fn from(path: Utf8PathBuf) -> PathBuf {
+        path.0
+    }
+}
+
+impl From<Utf8PathBuf> for Box<Path> {
+    fn from(path: Utf8PathBuf) -> Box<Path> {
+        PathBuf::from(path).into_boxed_path()
+    }
+}
+
+impl From<Utf8PathBuf> for Arc<Path> {
+    fn from(path: Utf8PathBuf) -> Arc<Path> {
+        PathBuf::from(path).into()
+    }
+}
+
+impl From<Utf8PathBuf> for Rc<Path> {
+    fn from(path: Utf8PathBuf) -> Rc<Path> {
+        PathBuf::from(path).into()
+    }
+}
+
+impl<'a> From<Utf8PathBuf> for Cow<'a, Path> {
+    fn from(path: Utf8PathBuf) -> Cow<'a, Path> {
+        PathBuf::from(path).into()
+    }
+}
+
+// ---
+// TryFrom impls
+// ---
+
+impl TryFrom<PathBuf> for Utf8PathBuf {
+    type Error = FromPathBufError;
+
+    fn try_from(path: PathBuf) -> Result<Utf8PathBuf, Self::Error> {
+        Utf8PathBuf::from_path_buf(path).map_err(|path| FromPathBufError {
+            path,
+            error: FromPathError(()),
+        })
+    }
+}
+
+impl<'a> TryFrom<&'a Path> for &'a Utf8Path {
+    type Error = FromPathError;
+
+    fn try_from(path: &'a Path) -> Result<&'a Utf8Path, Self::Error> {
+        Utf8Path::from_path(path).ok_or(FromPathError(()))
+    }
+}
+
+/// A possible error value while converting a [`PathBuf`] to a [`Utf8PathBuf`].
+///
+/// Produced by the `TryFrom<PathBuf>` implementation for [`Utf8PathBuf`].
+///
+/// # Examples
+///
+/// ```
+/// use camino::{Utf8PathBuf, FromPathBufError};
+/// use std::convert::{TryFrom, TryInto};
+/// use std::ffi::OsStr;
+/// # #[cfg(unix)]
+/// use std::os::unix::ffi::OsStrExt;
+/// use std::path::PathBuf;
+///
+/// let unicode_path = PathBuf::from("/valid/unicode");
+/// let utf8_path_buf: Utf8PathBuf = unicode_path.try_into().expect("valid Unicode path succeeded");
+///
+/// // Paths on Unix can be non-UTF-8.
+/// # #[cfg(unix)]
+/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF");
+/// # #[cfg(unix)]
+/// let non_unicode_path = PathBuf::from(non_unicode_str);
+/// # #[cfg(unix)]
+/// let err: FromPathBufError = Utf8PathBuf::try_from(non_unicode_path.clone())
+///     .expect_err("non-Unicode path failed");
+/// # #[cfg(unix)]
+/// assert_eq!(err.as_path(), &non_unicode_path);
+/// # #[cfg(unix)]
+/// assert_eq!(err.into_path_buf(), non_unicode_path);
+/// ```
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct FromPathBufError {
+    path: PathBuf,
+    error: FromPathError,
+}
+
+impl FromPathBufError {
+    /// Returns the [`Path`] slice that was attempted to be converted to [`Utf8PathBuf`].
+    pub fn as_path(&self) -> &Path {
+        &self.path
+    }
+
+    /// Returns the [`PathBuf`] that was attempted to be converted to [`Utf8PathBuf`].
+    pub fn into_path_buf(self) -> PathBuf {
+        self.path
+    }
+
+    /// Fetch a [`FromPathError`] for more about the conversion failure.
+    ///
+    /// At the moment this struct does not contain any additional information, but is provided for
+    /// completeness.
+    pub fn from_path_error(&self) -> FromPathError {
+        self.error
+    }
+}
+
+impl fmt::Display for FromPathBufError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "PathBuf contains invalid UTF-8: {}", self.path.display())
+    }
+}
+
+impl error::Error for FromPathBufError {
+    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+        Some(&self.error)
+    }
+}
+
+/// A possible error value while converting a [`Path`] to a [`Utf8Path`].
+///
+/// Produced by the `TryFrom<&Path>` implementation for [`&Utf8Path`](Utf8Path).
+///
+///
+/// # Examples
+///
+/// ```
+/// use camino::{Utf8Path, FromPathError};
+/// use std::convert::{TryFrom, TryInto};
+/// use std::ffi::OsStr;
+/// # #[cfg(unix)]
+/// use std::os::unix::ffi::OsStrExt;
+/// use std::path::Path;
+///
+/// let unicode_path = Path::new("/valid/unicode");
+/// let utf8_path: &Utf8Path = unicode_path.try_into().expect("valid Unicode path succeeded");
+///
+/// // Paths on Unix can be non-UTF-8.
+/// # #[cfg(unix)]
+/// let non_unicode_str = OsStr::from_bytes(b"\xFF\xFF\xFF");
+/// # #[cfg(unix)]
+/// let non_unicode_path = Path::new(non_unicode_str);
+/// # #[cfg(unix)]
+/// let err: FromPathError = <&Utf8Path>::try_from(non_unicode_path)
+///     .expect_err("non-Unicode path failed");
+/// ```
+#[derive(Copy, Clone, Debug, Eq, PartialEq)]
+pub struct FromPathError(());
+
+impl fmt::Display for FromPathError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "Path contains invalid UTF-8")
+    }
+}
+
+impl error::Error for FromPathError {
+    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+        None
+    }
+}
+
+// ---
+// AsRef impls
+// ---
+
+impl AsRef<Utf8Path> for Utf8Path {
+    fn as_ref(&self) -> &Utf8Path {
+        self
+    }
+}
+
+impl AsRef<Utf8Path> for Utf8PathBuf {
+    fn as_ref(&self) -> &Utf8Path {
+        self.as_path()
+    }
+}
+
+impl AsRef<Utf8Path> for str {
+    fn as_ref(&self) -> &Utf8Path {
+        Utf8Path::new(self)
+    }
+}
+
+impl AsRef<Utf8Path> for String {
+    fn as_ref(&self) -> &Utf8Path {
+        Utf8Path::new(self)
+    }
+}
+
+impl AsRef<Path> for Utf8Path {
+    fn as_ref(&self) -> &Path {
+        &self.0
+    }
+}
+
+impl AsRef<Path> for Utf8PathBuf {
+    fn as_ref(&self) -> &Path {
+        &*self.0
+    }
+}
+
+impl AsRef<str> for Utf8Path {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+
+impl AsRef<str> for Utf8PathBuf {
+    fn as_ref(&self) -> &str {
+        self.as_str()
+    }
+}
+
+impl AsRef<OsStr> for Utf8Path {
+    fn as_ref(&self) -> &OsStr {
+        self.as_os_str()
+    }
+}
+
+impl AsRef<OsStr> for Utf8PathBuf {
+    fn as_ref(&self) -> &OsStr {
+        self.as_os_str()
+    }
+}
+
+// ---
+// Borrow and ToOwned
+// ---
+
+impl Borrow<Utf8Path> for Utf8PathBuf {
+    fn borrow(&self) -> &Utf8Path {
+        self.as_path()
+    }
+}
+
+impl ToOwned for Utf8Path {
+    type Owned = Utf8PathBuf;
+
+    fn to_owned(&self) -> Utf8PathBuf {
+        self.to_path_buf()
+    }
+}
+
+impl<P: AsRef<Utf8Path>> std::iter::FromIterator<P> for Utf8PathBuf {
+    fn from_iter<I: IntoIterator<Item = P>>(iter: I) -> Utf8PathBuf {
+        let mut buf = Utf8PathBuf::new();
+        buf.extend(iter);
+        buf
+    }
+}
+
+// ---
+// [Partial]Eq, [Partial]Ord, Hash
+// ---
+
+impl PartialEq for Utf8PathBuf {
+    fn eq(&self, other: &Utf8PathBuf) -> bool {
+        self.components() == other.components()
+    }
+}
+
+impl Eq for Utf8PathBuf {}
+
+impl Hash for Utf8PathBuf {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.as_path().hash(state)
+    }
+}
+
+impl PartialOrd for Utf8PathBuf {
+    fn partial_cmp(&self, other: &Utf8PathBuf) -> Option<Ordering> {
+        self.components().partial_cmp(other.components())
+    }
+}
+
+impl Ord for Utf8PathBuf {
+    fn cmp(&self, other: &Utf8PathBuf) -> Ordering {
+        self.components().cmp(other.components())
+    }
+}
+
+impl PartialEq for Utf8Path {
+    fn eq(&self, other: &Utf8Path) -> bool {
+        self.components().eq(other.components())
+    }
+}
+
+impl Eq for Utf8Path {}
+
+impl Hash for Utf8Path {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        for component in self.components() {
+            component.hash(state)
+        }
+    }
+}
+
+impl PartialOrd for Utf8Path {
+    fn partial_cmp(&self, other: &Utf8Path) -> Option<Ordering> {
+        self.components().partial_cmp(other.components())
+    }
+}
+
+impl Ord for Utf8Path {
+    fn cmp(&self, other: &Utf8Path) -> Ordering {
+        self.components().cmp(other.components())
+    }
+}
+
+impl<'a> IntoIterator for &'a Utf8PathBuf {
+    type Item = &'a str;
+    type IntoIter = Iter<'a>;
+    fn into_iter(self) -> Iter<'a> {
+        self.iter()
+    }
+}
+
+impl<'a> IntoIterator for &'a Utf8Path {
+    type Item = &'a str;
+    type IntoIter = Iter<'a>;
+    fn into_iter(self) -> Iter<'a> {
+        self.iter()
+    }
+}
+
+macro_rules! impl_cmp {
+    ($lhs:ty, $rhs: ty) => {
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                <Utf8Path as PartialEq>::eq(self, other)
+            }
+        }
+
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                <Utf8Path as PartialEq>::eq(self, other)
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
+                <Utf8Path as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
+                <Utf8Path as PartialOrd>::partial_cmp(self, other)
+            }
+        }
+    };
+}
+
+impl_cmp!(Utf8PathBuf, Utf8Path);
+impl_cmp!(Utf8PathBuf, &'a Utf8Path);
+impl_cmp!(Cow<'a, Utf8Path>, Utf8Path);
+impl_cmp!(Cow<'a, Utf8Path>, &'b Utf8Path);
+impl_cmp!(Cow<'a, Utf8Path>, Utf8PathBuf);
+
+macro_rules! impl_cmp_std_path {
+    ($lhs:ty, $rhs: ty) => {
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                <Path as PartialEq>::eq(self.as_ref(), other)
+            }
+        }
+
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                <Path as PartialEq>::eq(self, other.as_ref())
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self.as_ref(), other)
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self, other.as_ref())
+            }
+        }
+    };
+}
+
+impl_cmp_std_path!(Utf8PathBuf, Path);
+impl_cmp_std_path!(Utf8PathBuf, &'a Path);
+impl_cmp_std_path!(Utf8PathBuf, Cow<'a, Path>);
+impl_cmp_std_path!(Utf8PathBuf, PathBuf);
+impl_cmp_std_path!(Utf8Path, Path);
+impl_cmp_std_path!(Utf8Path, &'a Path);
+impl_cmp_std_path!(Utf8Path, Cow<'a, Path>);
+impl_cmp_std_path!(Utf8Path, PathBuf);
+impl_cmp_std_path!(&'a Utf8Path, Path);
+impl_cmp_std_path!(&'a Utf8Path, Cow<'b, Path>);
+impl_cmp_std_path!(&'a Utf8Path, PathBuf);
+// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117)
+
+macro_rules! impl_cmp_str {
+    ($lhs:ty, $rhs: ty) => {
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                <Utf8Path as PartialEq>::eq(self, Utf8Path::new(other))
+            }
+        }
+
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                <Utf8Path as PartialEq>::eq(Utf8Path::new(self), other)
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> {
+                <Utf8Path as PartialOrd>::partial_cmp(self, Utf8Path::new(other))
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> {
+                <Utf8Path as PartialOrd>::partial_cmp(Utf8Path::new(self), other)
+            }
+        }
+    };
+}
+
+impl_cmp_str!(Utf8PathBuf, str);
+impl_cmp_str!(Utf8PathBuf, &'a str);
+impl_cmp_str!(Utf8PathBuf, Cow<'a, str>);
+impl_cmp_str!(Utf8PathBuf, String);
+impl_cmp_str!(Utf8Path, str);
+impl_cmp_str!(Utf8Path, &'a str);
+impl_cmp_str!(Utf8Path, Cow<'a, str>);
+impl_cmp_str!(Utf8Path, String);
+impl_cmp_str!(&'a Utf8Path, str);
+impl_cmp_str!(&'a Utf8Path, Cow<'b, str>);
+impl_cmp_str!(&'a Utf8Path, String);
+// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117)
+
+macro_rules! impl_cmp_os_str {
+    ($lhs:ty, $rhs: ty) => {
+        impl<'a, 'b> PartialEq<$rhs> for $lhs {
+            #[inline]
+            fn eq(&self, other: &$rhs) -> bool {
+                <Path as PartialEq>::eq(self.as_ref(), other.as_ref())
+            }
+        }
+
+        impl<'a, 'b> PartialEq<$lhs> for $rhs {
+            #[inline]
+            fn eq(&self, other: &$lhs) -> bool {
+                <Path as PartialEq>::eq(self.as_ref(), other.as_ref())
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$rhs> for $lhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$rhs) -> Option<std::cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref())
+            }
+        }
+
+        impl<'a, 'b> PartialOrd<$lhs> for $rhs {
+            #[inline]
+            fn partial_cmp(&self, other: &$lhs) -> Option<std::cmp::Ordering> {
+                <Path as PartialOrd>::partial_cmp(self.as_ref(), other.as_ref())
+            }
+        }
+    };
+}
+
+impl_cmp_os_str!(Utf8PathBuf, OsStr);
+impl_cmp_os_str!(Utf8PathBuf, &'a OsStr);
+impl_cmp_os_str!(Utf8PathBuf, Cow<'a, OsStr>);
+impl_cmp_os_str!(Utf8PathBuf, OsString);
+impl_cmp_os_str!(Utf8Path, OsStr);
+impl_cmp_os_str!(Utf8Path, &'a OsStr);
+impl_cmp_os_str!(Utf8Path, Cow<'a, OsStr>);
+impl_cmp_os_str!(Utf8Path, OsString);
+impl_cmp_os_str!(&'a Utf8Path, OsStr);
+impl_cmp_os_str!(&'a Utf8Path, Cow<'b, OsStr>);
+impl_cmp_os_str!(&'a Utf8Path, OsString);
+// NOTE: impls for Cow<'a, Utf8Path> cannot be defined because of the orphan rule (E0117)
+
+// invariant: OsStr must be guaranteed to be utf8 data
+unsafe fn assume_utf8(string: &OsStr) -> &str {
+    &*(string as *const OsStr as *const str)
+}
diff --git a/third_party/rust/camino/v1/crate/src/proptest_impls.rs b/third_party/rust/camino/v1/crate/src/proptest_impls.rs
new file mode 100644
index 0000000..997c88c
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/src/proptest_impls.rs
@@ -0,0 +1,61 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+//! [proptest::Arbitrary](Arbitrary) implementation for `Utf8PathBuf` and `Box<Utf8Path>`.  Note
+//! that implementions for `Rc<Utf8Path>` and `Arc<Utf8Path>` are not currently possible due to
+//! orphan rules - this crate doesn't define `Rc`/`Arc` nor `Arbitrary`, so it can't define those
+//! implementations.
+
+// NOTE: #[cfg(feature = "proptest1")] is specified here to work with `doc_cfg`.
+
+use proptest::{arbitrary::StrategyFor, prelude::*, strategy::MapInto};
+
+use crate::{Utf8Path, Utf8PathBuf};
+
+/// The [`Arbitrary`] impl for `Utf8PathBuf` returns a path with between 0 and 8 components,
+/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is
+/// randomly generated, and may itself contain one or more separators.)
+///
+/// On Unix, this generates an absolute path half of the time and a relative path the other half.
+///
+/// On Windows, this implementation doesn't currently generate
+/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might.
+#[cfg(feature = "proptest1")]
+impl Arbitrary for Utf8PathBuf {
+    type Parameters = <String as Arbitrary>::Parameters;
+    type Strategy = BoxedStrategy<Self>;
+
+    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+        (
+            any::<bool>(),
+            prop::collection::vec(any_with::<String>(args), 0..8),
+        )
+            .prop_map(|(is_relative, components)| {
+                let initial_component =
+                    is_relative.then(|| format!("{}", std::path::MAIN_SEPARATOR));
+                initial_component
+                    .into_iter()
+                    .chain(components.into_iter())
+                    .collect()
+            })
+            .boxed()
+    }
+}
+
+/// The [`Arbitrary`] impl for `Box<Utf8Path>` returns a path with between 0 and 8 components,
+/// joined by the [`MAIN_SEPARATOR`](std::path::MAIN_SEPARATOR) for the platform. (Each component is
+/// randomly generated, and may itself contain one or more separators.)
+///
+/// On Unix, this generates an absolute path half of the time and a relative path the other half.
+///
+/// On Windows, this implementation doesn't currently generate
+/// [`Utf8PrefixComponent`](crate::Utf8PrefixComponent) instances, though in the future it might.
+#[cfg(feature = "proptest1")]
+impl Arbitrary for Box<Utf8Path> {
+    type Parameters = <Utf8PathBuf as Arbitrary>::Parameters;
+    type Strategy = MapInto<StrategyFor<Utf8PathBuf>, Self>;
+
+    fn arbitrary_with(args: Self::Parameters) -> Self::Strategy {
+        any_with::<Utf8PathBuf>(args).prop_map_into()
+    }
+}
diff --git a/third_party/rust/camino/v1/crate/src/serde_impls.rs b/third_party/rust/camino/v1/crate/src/serde_impls.rs
new file mode 100644
index 0000000..d4c4eca
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/src/serde_impls.rs
@@ -0,0 +1,57 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+//! Serde implementations for `Utf8Path`.
+//!
+//! The Serde implementations for `Utf8PathBuf` are derived, but `Utf8Path` is an unsized type which
+//! the derive impls can't handle. Implement these by hand.
+
+use crate::Utf8Path;
+use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
+use std::fmt;
+
+struct Utf8PathVisitor;
+
+impl<'a> de::Visitor<'a> for Utf8PathVisitor {
+    type Value = &'a Utf8Path;
+
+    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+        formatter.write_str("a borrowed path")
+    }
+
+    fn visit_borrowed_str<E>(self, v: &'a str) -> Result<Self::Value, E>
+    where
+        E: de::Error,
+    {
+        Ok(v.as_ref())
+    }
+
+    fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
+    where
+        E: de::Error,
+    {
+        std::str::from_utf8(v)
+            .map(AsRef::as_ref)
+            .map_err(|_| de::Error::invalid_value(de::Unexpected::Bytes(v), &self))
+    }
+}
+
+#[cfg(feature = "serde1")]
+impl<'de: 'a, 'a> Deserialize<'de> for &'a Utf8Path {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        deserializer.deserialize_str(Utf8PathVisitor)
+    }
+}
+
+#[cfg(feature = "serde1")]
+impl Serialize for Utf8Path {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        self.as_str().serialize(serializer)
+    }
+}
diff --git a/third_party/rust/camino/v1/crate/src/tests.rs b/third_party/rust/camino/v1/crate/src/tests.rs
new file mode 100644
index 0000000..305b7609
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/src/tests.rs
@@ -0,0 +1,46 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+// Test that all required impls exist.
+
+use crate::{Utf8Path, Utf8PathBuf};
+use std::{
+    borrow::Cow,
+    path::{Path, PathBuf},
+    rc::Rc,
+    sync::Arc,
+};
+
+macro_rules! all_into {
+    ($t:ty, $x:ident) => {
+        test_into::<$t, Utf8PathBuf>($x.clone());
+        test_into::<$t, Box<Utf8Path>>($x.clone());
+        test_into::<$t, Arc<Utf8Path>>($x.clone());
+        test_into::<$t, Rc<Utf8Path>>($x.clone());
+        test_into::<$t, Cow<'_, Utf8Path>>($x.clone());
+        test_into::<$t, PathBuf>($x.clone());
+        test_into::<$t, Box<Path>>($x.clone());
+        test_into::<$t, Arc<Path>>($x.clone());
+        test_into::<$t, Rc<Path>>($x.clone());
+        test_into::<$t, Cow<'_, Path>>($x.clone());
+    };
+}
+
+#[test]
+fn test_borrowed_into() {
+    let utf8_path = Utf8Path::new("test/path");
+    all_into!(&Utf8Path, utf8_path);
+}
+
+#[test]
+fn test_owned_into() {
+    let utf8_path_buf = Utf8PathBuf::from("test/path");
+    all_into!(Utf8PathBuf, utf8_path_buf);
+}
+
+fn test_into<T, U>(orig: T)
+where
+    T: Into<U>,
+{
+    let _ = orig.into();
+}
diff --git a/third_party/rust/camino/v1/crate/tests/integration_tests.rs b/third_party/rust/camino/v1/crate/tests/integration_tests.rs
new file mode 100644
index 0000000..a8b00f2f
--- /dev/null
+++ b/third_party/rust/camino/v1/crate/tests/integration_tests.rs
@@ -0,0 +1,115 @@
+// Copyright (c) The camino Contributors
+// SPDX-License-Identifier: MIT OR Apache-2.0
+
+use camino::{Utf8Path, Utf8PathBuf};
+use std::{
+    collections::hash_map::DefaultHasher,
+    hash::{Hash, Hasher},
+    path::Path,
+};
+
+static PATH_CORPUS: &[&str] = &[
+    "",
+    "foo",
+    "foo/bar",
+    "foo//bar",
+    "foo/bar/baz",
+    "foo/bar/./baz",
+    "foo/bar/../baz",
+    "../foo/bar/./../baz",
+    "/foo",
+    "/foo/bar",
+    "/",
+    "///",
+    // ---
+    // Windows-only paths
+    // ---
+    #[cfg(windows)]
+    "foo\\bar",
+    #[cfg(windows)]
+    "\\foo\\bar",
+    #[cfg(windows)]
+    "C:\\foo",
+    #[cfg(windows)]
+    "C:foo\\bar",
+    #[cfg(windows)]
+    "C:\\foo\\..\\.\\bar",
+    #[cfg(windows)]
+    "\\\\server\\foo\\bar",
+    #[cfg(windows)]
+    "\\\\.\\C:\\foo\\bar.txt",
+];
+
+#[test]
+fn test_borrow_eq_ord() {
+    // Utf8PathBuf implements Borrow<Utf8Path> so equality and ordering comparisons should
+    // match.
+    for (idx, &path1) in PATH_CORPUS.iter().enumerate() {
+        for &path2 in &PATH_CORPUS[idx..] {
+            let borrowed1 = Utf8Path::new(path1);
+            let borrowed2 = Utf8Path::new(path2);
+            let owned1 = Utf8PathBuf::from(path1);
+            let owned2 = Utf8PathBuf::from(path2);
+
+            assert_eq!(
+                borrowed1 == borrowed2,
+                owned1 == owned2,
+                "Eq impls match: {} == {}",
+                borrowed1,
+                borrowed2
+            );
+            assert_eq!(
+                borrowed1.cmp(borrowed2),
+                owned1.cmp(&owned2),
+                "Ord impls match: {} and {}",
+                borrowed1,
+                borrowed2
+            );
+
+            // Also check against std paths.
+            let std1 = Path::new(path1);
+            let std2 = Path::new(path2);
+            assert_eq!(
+                borrowed1, std1,
+                "Eq between Path and Utf8Path: {}",
+                borrowed1
+            );
+            assert_eq!(
+                borrowed1 == borrowed2,
+                std1 == std2,
+                "Eq impl matches Path: {} == {}",
+                borrowed1,
+                borrowed2
+            );
+            assert_eq!(
+                borrowed1.cmp(borrowed2),
+                std1.cmp(std2),
+                "Ord impl matches Path: {} and {}",
+                borrowed1,
+                borrowed2
+            );
+        }
+    }
+}
+
+#[test]
+fn test_borrow_hash() {
+    // Utf8PathBuf implements Borrow<Utf8Path> so hash comparisons should match.
+    fn hash_output(x: impl Hash) -> u64 {
+        let mut hasher = DefaultHasher::new();
+        x.hash(&mut hasher);
+        hasher.finish()
+    }
+
+    for &path in PATH_CORPUS {
+        let borrowed = Utf8Path::new(path);
+        let owned = Utf8PathBuf::from(path);
+
+        assert_eq!(
+            hash_output(&owned),
+            hash_output(borrowed),
+            "consistent Hash: {}",
+            borrowed
+        );
+    }
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/BUILD.gn b/third_party/rust/cargo_metadata/v0_14/BUILD.gn
new file mode 100644
index 0000000..5d339738
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/BUILD.gn
@@ -0,0 +1,28 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/cargo_crate.gni")
+
+cargo_crate("test_support") {
+  crate_name = "cargo_metadata"
+  epoch = "0.14"
+  crate_type = "rlib"
+  testonly = "true"
+  crate_root = "crate/src/lib.rs"
+  build_native_rust_unit_tests = false
+  sources = [ "crate/src/lib.rs" ]
+  edition = "2018"
+  cargo_pkg_version = "0.14.2"
+  cargo_pkg_authors =
+      "Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"
+  cargo_pkg_name = "cargo_metadata"
+  cargo_pkg_description = "structured access to the output of `cargo metadata`"
+  deps = [
+    "//third_party/rust/camino/v1:lib",
+    "//third_party/rust/cargo_platform/v0_1:lib",
+    "//third_party/rust/semver/v1:lib",
+    "//third_party/rust/serde/v1:lib",
+    "//third_party/rust/serde_json/v1:lib",
+  ]
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/README.chromium b/third_party/rust/cargo_metadata/v0_14/README.chromium
new file mode 100644
index 0000000..ac8329c6
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/README.chromium
@@ -0,0 +1,6 @@
+Name: cargo_metadata
+URL: https://crates.io/crates/cargo_metadata
+Description: structured access to the output of `cargo metadata`
+Version: 0.14.2
+Security Critical: no
+License: MIT
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json b/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json
new file mode 100644
index 0000000..fa70ceff
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/.cargo_vcs_info.json
@@ -0,0 +1,6 @@
+{
+  "git": {
+    "sha1": "f615f7164534eb52fb9525bdb5eee5731f652968"
+  },
+  "path_in_vcs": ""
+}
\ No newline at end of file
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml b/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml
new file mode 100644
index 0000000..8a97ed4
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/.github/workflows/main.yml
@@ -0,0 +1,35 @@
+name: CI
+on: [push, pull_request]
+
+jobs:
+  rustfmt:
+    name: rustfmt
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install rust
+      run: rustup update --no-self-update stable && rustup default stable
+    - name: Check formatting
+      run: cargo fmt -- --check
+
+  test:
+    name: Test
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        include:
+          - rust: stable
+          - rust: beta
+          - rust: nightly
+          - rust: 1.40.0
+    steps:
+    - uses: actions/checkout@v2
+    - name: Install rust
+      run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
+    - name: Run tests
+      run: |
+        cargo build --verbose
+        cargo build --verbose --no-default-features
+        cargo test --verbose
+        cargo test --verbose --no-default-features
+        cargo test --verbose --all-features
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/.gitignore b/third_party/rust/cargo_metadata/v0_14/crate/.gitignore
new file mode 100644
index 0000000..34856db
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/.gitignore
@@ -0,0 +1,3 @@
+Cargo.lock
+.idea/
+target
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml
new file mode 100644
index 0000000..cbb937e
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml
@@ -0,0 +1,49 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "cargo_metadata"
+version = "0.14.2"
+authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"]
+description = "structured access to the output of `cargo metadata`"
+readme = "README.md"
+license = "MIT"
+repository = "https://github.com/oli-obk/cargo_metadata"
+[package.metadata.cargo_metadata_test]
+other_field = "foo"
+some_field = true
+[dependencies.camino]
+version = "1.0.1"
+features = ["serde1"]
+
+[dependencies.cargo-platform]
+version = "0.1"
+
+[dependencies.derive_builder]
+version = "0.9.0"
+optional = true
+
+[dependencies.semver]
+version = "1"
+features = ["serde"]
+
+[dependencies.serde]
+version = "1.0.107"
+features = ["derive"]
+
+[dependencies.serde_json]
+version = "1.0.59"
+features = ["unbounded_depth"]
+
+[features]
+builder = ["derive_builder"]
+default = []
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig
new file mode 100644
index 0000000..c34928a
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/Cargo.toml.orig
@@ -0,0 +1,25 @@
+[package]
+name = "cargo_metadata"
+version = "0.14.2"
+authors = ["Oliver Schneider <git-spam-no-reply9815368754983@oli-obk.de>"]
+repository = "https://github.com/oli-obk/cargo_metadata"
+description = "structured access to the output of `cargo metadata`"
+license = "MIT"
+readme = "README.md"
+edition = "2018"
+
+[dependencies]
+camino = { version = "1.0.1", features = ["serde1"] }
+cargo-platform = "0.1"
+derive_builder = { version = "0.9.0", optional = true }
+semver = { version = "1", features = ["serde"] }
+serde = { version = "1.0.107", features = ["derive"] }
+serde_json = { version = "1.0.59", features = ["unbounded_depth"] }
+
+[features]
+default = []
+builder = ["derive_builder"]
+
+[package.metadata.cargo_metadata_test]
+some_field = true
+other_field = "foo"
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT b/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT
new file mode 100644
index 0000000..31aa7938
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/LICENSE-MIT
@@ -0,0 +1,23 @@
+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
+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.
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/README.md b/third_party/rust/cargo_metadata/v0_14/crate/README.md
new file mode 100644
index 0000000..03743f3
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/README.md
@@ -0,0 +1,12 @@
+# cargo_metadata
+
+Structured access to the output of `cargo metadata`. Usually used from within a `cargo-*` executable.
+
+Also supports serialization to aid in implementing `--message-format=json`-like
+output generation in `cargo-*` subcommands, since some of the types in what
+`cargo --message-format=json` emits are exactly the same as the ones from `cargo metadata`.
+
+[![Build Status](https://api.travis-ci.org/oli-obk/cargo_metadata.svg?branch=master)](https://travis-ci.org/oli-obk/cargo_metadata)
+[![crates.io](https://img.shields.io/crates/v/cargo_metadata.svg)](https://crates.io/crates/cargo_metadata)
+
+[Documentation](https://docs.rs/cargo_metadata/)
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs
new file mode 100644
index 0000000..89bcf9f2
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/src/dependency.rs
@@ -0,0 +1,90 @@
+//! This module contains `Dependency` and the types/functions it uses for deserialization.
+
+use std::fmt;
+
+use camino::Utf8PathBuf;
+#[cfg(feature = "builder")]
+use derive_builder::Builder;
+use semver::VersionReq;
+use serde::{Deserialize, Deserializer, Serialize};
+
+#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash, Serialize, Deserialize)]
+/// Dependencies can come in three kinds
+pub enum DependencyKind {
+    #[serde(rename = "normal")]
+    /// The 'normal' kind
+    Normal,
+    #[serde(rename = "dev")]
+    /// Those used in tests only
+    Development,
+    #[serde(rename = "build")]
+    /// Those used in build scripts only
+    Build,
+    #[doc(hidden)]
+    #[serde(other)]
+    Unknown,
+}
+
+impl Default for DependencyKind {
+    fn default() -> DependencyKind {
+        DependencyKind::Normal
+    }
+}
+
+impl fmt::Display for DependencyKind {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let s = serde_json::to_string(self).unwrap();
+        // skip opening and closing quotes
+        f.write_str(&s[1..s.len() - 1])
+    }
+}
+
+/// The `kind` can be `null`, which is interpreted as the default - `Normal`.
+pub(super) fn parse_dependency_kind<'de, D>(d: D) -> Result<DependencyKind, D::Error>
+where
+    D: Deserializer<'de>,
+{
+    Deserialize::deserialize(d).map(|x: Option<_>| x.unwrap_or_default())
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// A dependency of the main crate
+pub struct Dependency {
+    /// Name as given in the `Cargo.toml`
+    pub name: String,
+    /// The source of dependency
+    pub source: Option<String>,
+    /// The required version
+    pub req: VersionReq,
+    /// The kind of dependency this is
+    #[serde(deserialize_with = "parse_dependency_kind")]
+    pub kind: DependencyKind,
+    /// Whether this dependency is required or optional
+    pub optional: bool,
+    /// Whether the default features in this dependency are used.
+    pub uses_default_features: bool,
+    /// The list of features enabled for this dependency.
+    pub features: Vec<String>,
+    /// The target this dependency is specific to.
+    ///
+    /// Use the [`Display`] trait to access the contents.
+    ///
+    /// [`Display`]: std::fmt::Display
+    pub target: Option<Platform>,
+    /// If the dependency is renamed, this is the new name for the dependency
+    /// as a string.  None if it is not renamed.
+    pub rename: Option<String>,
+    /// The URL of the index of the registry where this dependency is from.
+    ///
+    /// If None, the dependency is from crates.io.
+    pub registry: Option<String>,
+    /// The file system path for a local path dependency.
+    ///
+    /// Only produced on cargo 1.51+
+    pub path: Option<Utf8PathBuf>,
+}
+
+pub use cargo_platform::Platform;
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs
new file mode 100644
index 0000000..dbe2112
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/src/diagnostic.rs
@@ -0,0 +1,160 @@
+//! This module contains `Diagnostic` and the types/functions it uses for deserialization.
+
+#[cfg(feature = "builder")]
+use derive_builder::Builder;
+use serde::{Deserialize, Serialize};
+use std::fmt;
+
+/// The error code associated to this diagnostic.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct DiagnosticCode {
+    /// The code itself.
+    pub code: String,
+    /// An explanation for the code
+    pub explanation: Option<String>,
+}
+
+/// A line of code associated with the Diagnostic
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct DiagnosticSpanLine {
+    /// The line of code associated with the error
+    pub text: String,
+    /// Start of the section of the line to highlight. 1-based, character offset in self.text
+    pub highlight_start: usize,
+    /// End of the section of the line to highlight. 1-based, character offset in self.text
+    pub highlight_end: usize,
+}
+
+/// Macro expansion information associated with a diagnostic.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct DiagnosticSpanMacroExpansion {
+    /// span where macro was applied to generate this code; note that
+    /// this may itself derive from a macro (if
+    /// `span.expansion.is_some()`)
+    pub span: DiagnosticSpan,
+
+    /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]")
+    pub macro_decl_name: String,
+
+    /// span where macro was defined (if known)
+    pub def_site_span: Option<DiagnosticSpan>,
+}
+
+/// A section of the source code associated with a Diagnostic
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct DiagnosticSpan {
+    /// The file name or the macro name this diagnostic comes from.
+    pub file_name: String,
+    /// The byte offset in the file where this diagnostic starts from.
+    pub byte_start: u32,
+    /// The byte offset in the file where this diagnostic ends.
+    pub byte_end: u32,
+    /// 1-based. The line in the file.
+    pub line_start: usize,
+    /// 1-based. The line in the file.
+    pub line_end: usize,
+    /// 1-based, character offset.
+    pub column_start: usize,
+    /// 1-based, character offset.
+    pub column_end: usize,
+    /// Is this a "primary" span -- meaning the point, or one of the points,
+    /// where the error occurred?
+    ///
+    /// There are rare cases where multiple spans are marked as primary,
+    /// e.g. "immutable borrow occurs here" and "mutable borrow ends here" can
+    /// be two separate spans both "primary". Top (parent) messages should
+    /// always have at least one primary span, unless it has 0 spans. Child
+    /// messages may have 0 or more primary spans.
+    pub is_primary: bool,
+    /// Source text from the start of line_start to the end of line_end.
+    pub text: Vec<DiagnosticSpanLine>,
+    /// Label that should be placed at this location (if any)
+    pub label: Option<String>,
+    /// If we are suggesting a replacement, this will contain text
+    /// that should be sliced in atop this span.
+    pub suggested_replacement: Option<String>,
+    /// If the suggestion is approximate
+    pub suggestion_applicability: Option<Applicability>,
+    /// Macro invocations that created the code at this span, if any.
+    pub expansion: Option<Box<DiagnosticSpanMacroExpansion>>,
+}
+
+/// Whether a suggestion can be safely applied.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[non_exhaustive]
+pub enum Applicability {
+    /// The suggested replacement can be applied automatically safely
+    MachineApplicable,
+    /// The suggested replacement has placeholders that will need to be manually
+    /// replaced.
+    HasPlaceholders,
+    /// The suggested replacement may be incorrect in some circumstances. Needs
+    /// human review.
+    MaybeIncorrect,
+    /// The suggested replacement will probably not work.
+    Unspecified,
+}
+
+/// The diagnostic level
+#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[non_exhaustive]
+#[serde(rename_all = "lowercase")]
+pub enum DiagnosticLevel {
+    /// Internal compiler error
+    #[serde(rename = "error: internal compiler error")]
+    Ice,
+    /// Error
+    Error,
+    /// Warning
+    Warning,
+    /// Failure note
+    #[serde(rename = "failure-note")]
+    FailureNote,
+    /// Note
+    Note,
+    /// Help
+    Help,
+}
+
+/// A diagnostic message generated by rustc
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct Diagnostic {
+    /// The error message of this diagnostic.
+    pub message: String,
+    /// The associated error code for this diagnostic
+    pub code: Option<DiagnosticCode>,
+    /// "error: internal compiler error", "error", "warning", "note", "help"
+    pub level: DiagnosticLevel,
+    /// A list of source code spans this diagnostic is associated with.
+    pub spans: Vec<DiagnosticSpan>,
+    /// Associated diagnostic messages.
+    pub children: Vec<Diagnostic>,
+    /// The message as rustc would render it
+    pub rendered: Option<String>,
+}
+
+impl fmt::Display for Diagnostic {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if let Some(ref rendered) = self.rendered {
+            f.write_str(rendered)?;
+        } else {
+            f.write_str("cargo didn't render this message")?;
+        }
+        Ok(())
+    }
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs
new file mode 100644
index 0000000..7172057e
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/src/errors.rs
@@ -0,0 +1,110 @@
+use std::fmt;
+use std::io;
+use std::str::Utf8Error;
+use std::string::FromUtf8Error;
+
+/// Custom result type for `cargo_metadata::Error`
+pub type Result<T> = ::std::result::Result<T, Error>;
+
+/// Error returned when executing/parsing `cargo metadata` fails.
+///
+/// # Note about Backtraces
+///
+/// This error type does not contain backtraces, but each error variant
+/// comes from _one_ specific place, so it's not really needed for the
+/// inside of this crate. If you need a backtrace down to, but not inside
+/// of, a failed call of `cargo_metadata` you can do one of multiple thinks:
+///
+/// 1. Convert it to a `failure::Error` (possible using the `?` operator),
+///    which is similar to a `Box<::std::error::Error + 'static + Send  + Sync>`.
+/// 2. Have appropriate variants in your own error type. E.g. you could wrap
+///    a `failure::Context<Error>` or add a `failure::Backtrace` field (which
+///    is empty if `RUST_BACKTRACE` is not set, so it's simple to use).
+/// 3. You still can place a failure based error into a `error_chain` if you
+///    really want to. (Either through foreign_links or by making it a field
+///    value of a `ErrorKind` variant).
+///
+#[derive(Debug)]
+pub enum Error {
+    /// Error during execution of `cargo metadata`
+    CargoMetadata {
+        /// stderr returned by the `cargo metadata` command
+        stderr: String,
+    },
+
+    /// IO Error during execution of `cargo metadata`
+    Io(io::Error),
+
+    /// Output of `cargo metadata` was not valid utf8
+    Utf8(Utf8Error),
+
+    /// Error output of `cargo metadata` was not valid utf8
+    ErrUtf8(FromUtf8Error),
+
+    /// Deserialization error (structure of json did not match expected structure)
+    Json(::serde_json::Error),
+
+    /// The output did not contain any json
+    NoJson,
+}
+
+impl From<io::Error> for Error {
+    fn from(v: io::Error) -> Self {
+        Error::Io(v)
+    }
+}
+
+impl From<Utf8Error> for Error {
+    fn from(v: Utf8Error) -> Self {
+        Error::Utf8(v)
+    }
+}
+
+impl From<FromUtf8Error> for Error {
+    fn from(v: FromUtf8Error) -> Self {
+        Error::ErrUtf8(v)
+    }
+}
+
+impl From<::serde_json::Error> for Error {
+    fn from(v: ::serde_json::Error) -> Self {
+        Error::Json(v)
+    }
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Error::CargoMetadata { stderr } => {
+                write!(
+                    f,
+                    "`cargo metadata` exited with an error: {}",
+                    stderr.trim_end()
+                )
+            }
+            Error::Io(err) => write!(f, "failed to start `cargo metadata`: {}", err),
+            Error::Utf8(err) => write!(f, "cannot convert the stdout of `cargo metadata`: {}", err),
+            Error::ErrUtf8(err) => {
+                write!(f, "cannot convert the stderr of `cargo metadata`: {}", err)
+            }
+            Error::Json(err) => write!(f, "failed to interpret `cargo metadata`'s json: {}", err),
+            Error::NoJson => write!(
+                f,
+                "could not find any json in the output of `cargo metadata`"
+            ),
+        }
+    }
+}
+
+impl ::std::error::Error for Error {
+    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
+        match self {
+            Error::CargoMetadata { .. } => None,
+            Error::Io(err) => Some(err),
+            Error::Utf8(err) => Some(err),
+            Error::ErrUtf8(err) => Some(err),
+            Error::Json(err) => Some(err),
+            Error::NoJson => None,
+        }
+    }
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs
new file mode 100644
index 0000000..c88d324
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/src/lib.rs
@@ -0,0 +1,641 @@
+#![deny(missing_docs)]
+//! Structured access to the output of `cargo metadata` and `cargo --message-format=json`.
+//! Usually used from within a `cargo-*` executable
+//!
+//! See the [cargo book](https://doc.rust-lang.org/cargo/index.html) for
+//! details on cargo itself.
+//!
+//! ## Examples
+//!
+//! ```rust
+//! # extern crate cargo_metadata;
+//! # use std::path::Path;
+//! let mut args = std::env::args().skip_while(|val| !val.starts_with("--manifest-path"));
+//!
+//! let mut cmd = cargo_metadata::MetadataCommand::new();
+//! let manifest_path = match args.next() {
+//!     Some(ref p) if p == "--manifest-path" => {
+//!         cmd.manifest_path(args.next().unwrap());
+//!     }
+//!     Some(p) => {
+//!         cmd.manifest_path(p.trim_start_matches("--manifest-path="));
+//!     }
+//!     None => {}
+//! };
+//!
+//! let _metadata = cmd.exec().unwrap();
+//! ```
+//!
+//! Pass features flags
+//!
+//! ```rust
+//! # // This should be kept in sync with the equivalent example in the readme.
+//! # extern crate cargo_metadata;
+//! # use std::path::Path;
+//! # fn main() {
+//! use cargo_metadata::{MetadataCommand, CargoOpt};
+//!
+//! let _metadata = MetadataCommand::new()
+//!     .manifest_path("./Cargo.toml")
+//!     .features(CargoOpt::AllFeatures)
+//!     .exec()
+//!     .unwrap();
+//! # }
+//! ```
+//!
+//! Parse message-format output:
+//!
+//! ```
+//! # extern crate cargo_metadata;
+//! use std::process::{Stdio, Command};
+//! use cargo_metadata::Message;
+//!
+//! let mut command = Command::new("cargo")
+//!     .args(&["build", "--message-format=json-render-diagnostics"])
+//!     .stdout(Stdio::piped())
+//!     .spawn()
+//!     .unwrap();
+//!
+//! let reader = std::io::BufReader::new(command.stdout.take().unwrap());
+//! for message in cargo_metadata::Message::parse_stream(reader) {
+//!     match message.unwrap() {
+//!         Message::CompilerMessage(msg) => {
+//!             println!("{:?}", msg);
+//!         },
+//!         Message::CompilerArtifact(artifact) => {
+//!             println!("{:?}", artifact);
+//!         },
+//!         Message::BuildScriptExecuted(script) => {
+//!             println!("{:?}", script);
+//!         },
+//!         Message::BuildFinished(finished) => {
+//!             println!("{:?}", finished);
+//!         },
+//!         _ => () // Unknown message
+//!     }
+//! }
+//!
+//! let output = command.wait().expect("Couldn't get cargo's exit status");
+//! ```
+
+use camino::Utf8PathBuf;
+#[cfg(feature = "builder")]
+use derive_builder::Builder;
+use std::collections::HashMap;
+use std::env;
+use std::fmt;
+use std::path::PathBuf;
+use std::process::Command;
+use std::str::from_utf8;
+
+pub use camino;
+pub use semver::{Version, VersionReq};
+
+pub use dependency::{Dependency, DependencyKind};
+use diagnostic::Diagnostic;
+pub use errors::{Error, Result};
+#[allow(deprecated)]
+pub use messages::parse_messages;
+pub use messages::{
+    Artifact, ArtifactProfile, BuildFinished, BuildScript, CompilerMessage, Message, MessageIter,
+};
+use serde::{Deserialize, Serialize};
+
+mod dependency;
+pub mod diagnostic;
+mod errors;
+mod messages;
+
+/// An "opaque" identifier for a package.
+/// It is possible to inspect the `repr` field, if the need arises, but its
+/// precise format is an implementation detail and is subject to change.
+///
+/// `Metadata` can be indexed by `PackageId`.
+#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[serde(transparent)]
+pub struct PackageId {
+    /// The underlying string representation of id.
+    pub repr: String,
+}
+
+impl std::fmt::Display for PackageId {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.repr, f)
+    }
+}
+
+// Helpers for default metadata fields
+fn is_null(value: &serde_json::Value) -> bool {
+    match value {
+        serde_json::Value::Null => true,
+        _ => false,
+    }
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// Starting point for metadata returned by `cargo metadata`
+pub struct Metadata {
+    /// A list of all crates referenced by this crate (and the crate itself)
+    pub packages: Vec<Package>,
+    /// A list of all workspace members
+    pub workspace_members: Vec<PackageId>,
+    /// Dependencies graph
+    pub resolve: Option<Resolve>,
+    /// Workspace root
+    pub workspace_root: Utf8PathBuf,
+    /// Build directory
+    pub target_directory: Utf8PathBuf,
+    /// The workspace-level metadata object. Null if non-existent.
+    #[serde(rename = "metadata", default, skip_serializing_if = "is_null")]
+    pub workspace_metadata: serde_json::Value,
+    /// The metadata format version
+    version: usize,
+}
+
+impl Metadata {
+    /// Get the root package of this metadata instance.
+    pub fn root_package(&self) -> Option<&Package> {
+        let root = self.resolve.as_ref()?.root.as_ref()?;
+        self.packages.iter().find(|pkg| &pkg.id == root)
+    }
+}
+
+impl<'a> std::ops::Index<&'a PackageId> for Metadata {
+    type Output = Package;
+
+    fn index(&self, idx: &'a PackageId) -> &Package {
+        self.packages
+            .iter()
+            .find(|p| p.id == *idx)
+            .unwrap_or_else(|| panic!("no package with this id: {:?}", idx))
+    }
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// A dependency graph
+pub struct Resolve {
+    /// Nodes in a dependencies graph
+    pub nodes: Vec<Node>,
+
+    /// The crate for which the metadata was read.
+    pub root: Option<PackageId>,
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// A node in a dependencies graph
+pub struct Node {
+    /// An opaque identifier for a package
+    pub id: PackageId,
+    /// Dependencies in a structured format.
+    ///
+    /// `deps` handles renamed dependencies whereas `dependencies` does not.
+    #[serde(default)]
+    pub deps: Vec<NodeDep>,
+
+    /// List of opaque identifiers for this node's dependencies.
+    /// It doesn't support renamed dependencies. See `deps`.
+    pub dependencies: Vec<PackageId>,
+
+    /// Features enabled on the crate
+    #[serde(default)]
+    pub features: Vec<String>,
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// A dependency in a node
+pub struct NodeDep {
+    /// The name of the dependency's library target.
+    /// If the crate was renamed, it is the new name.
+    pub name: String,
+    /// Package ID (opaque unique identifier)
+    pub pkg: PackageId,
+    /// The kinds of dependencies.
+    ///
+    /// This field was added in Rust 1.41.
+    #[serde(default)]
+    pub dep_kinds: Vec<DepKindInfo>,
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// Information about a dependency kind.
+pub struct DepKindInfo {
+    /// The kind of dependency.
+    #[serde(deserialize_with = "dependency::parse_dependency_kind")]
+    pub kind: DependencyKind,
+    /// The target platform for the dependency.
+    ///
+    /// This is `None` if it is not a target dependency.
+    ///
+    /// Use the [`Display`] trait to access the contents.
+    ///
+    /// By default all platform dependencies are included in the resolve
+    /// graph. Use Cargo's `--filter-platform` flag if you only want to
+    /// include dependencies for a specific platform.
+    ///
+    /// [`Display`]: std::fmt::Display
+    pub target: Option<dependency::Platform>,
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+/// One or more crates described by a single `Cargo.toml`
+///
+/// Each [`target`][Package::targets] of a `Package` will be built as a crate.
+/// For more information, see <https://doc.rust-lang.org/book/ch07-01-packages-and-crates.html>.
+pub struct Package {
+    /// Name as given in the `Cargo.toml`
+    pub name: String,
+    /// Version given in the `Cargo.toml`
+    pub version: Version,
+    /// Authors given in the `Cargo.toml`
+    #[serde(default)]
+    pub authors: Vec<String>,
+    /// An opaque identifier for a package
+    pub id: PackageId,
+    /// The source of the package, e.g.
+    /// crates.io or `None` for local projects.
+    pub source: Option<Source>,
+    /// Description as given in the `Cargo.toml`
+    pub description: Option<String>,
+    /// List of dependencies of this particular package
+    pub dependencies: Vec<Dependency>,
+    /// License as given in the `Cargo.toml`
+    pub license: Option<String>,
+    /// If the package is using a nonstandard license, this key may be specified instead of
+    /// `license`, and must point to a file relative to the manifest.
+    pub license_file: Option<Utf8PathBuf>,
+    /// Targets provided by the crate (lib, bin, example, test, ...)
+    pub targets: Vec<Target>,
+    /// Features provided by the crate, mapped to the features required by that feature.
+    pub features: HashMap<String, Vec<String>>,
+    /// Path containing the `Cargo.toml`
+    pub manifest_path: Utf8PathBuf,
+    /// Categories as given in the `Cargo.toml`
+    #[serde(default)]
+    pub categories: Vec<String>,
+    /// Keywords as given in the `Cargo.toml`
+    #[serde(default)]
+    pub keywords: Vec<String>,
+    /// Readme as given in the `Cargo.toml`
+    pub readme: Option<Utf8PathBuf>,
+    /// Repository as given in the `Cargo.toml`
+    // can't use `url::Url` because that requires a more recent stable compiler
+    pub repository: Option<String>,
+    /// Homepage as given in the `Cargo.toml`
+    ///
+    /// On versions of cargo before 1.49, this will always be [`None`].
+    pub homepage: Option<String>,
+    /// Documentation URL as given in the `Cargo.toml`
+    ///
+    /// On versions of cargo before 1.49, this will always be [`None`].
+    pub documentation: Option<String>,
+    /// Default Rust edition for the package
+    ///
+    /// Beware that individual targets may specify their own edition in
+    /// [`Target::edition`].
+    #[serde(default = "edition_default")]
+    pub edition: String,
+    /// Contents of the free form package.metadata section
+    ///
+    /// This contents can be serialized to a struct using serde:
+    ///
+    /// ```rust
+    /// use serde::Deserialize;
+    /// use serde_json::json;
+    ///
+    /// #[derive(Debug, Deserialize)]
+    /// struct SomePackageMetadata {
+    ///     some_value: i32,
+    /// }
+    ///
+    /// fn main() {
+    ///     let value = json!({
+    ///         "some_value": 42,
+    ///     });
+    ///
+    ///     let package_metadata: SomePackageMetadata = serde_json::from_value(value).unwrap();
+    ///     assert_eq!(package_metadata.some_value, 42);
+    /// }
+    ///
+    /// ```
+    #[serde(default, skip_serializing_if = "is_null")]
+    pub metadata: serde_json::Value,
+    /// The name of a native library the package is linking to.
+    pub links: Option<String>,
+    /// List of registries to which this package may be published.
+    ///
+    /// Publishing is unrestricted if `None`, and forbidden if the `Vec` is empty.
+    ///
+    /// This is always `None` if running with a version of Cargo older than 1.39.
+    pub publish: Option<Vec<String>>,
+    /// The default binary to run by `cargo run`.
+    ///
+    /// This is always `None` if running with a version of Cargo older than 1.55.
+    pub default_run: Option<String>,
+    /// The minimum supported Rust version of this package.
+    ///
+    /// This is always `None` if running with a version of Cargo older than 1.58.
+    pub rust_version: Option<VersionReq>,
+}
+
+impl Package {
+    /// Full path to the license file if one is present in the manifest
+    pub fn license_file(&self) -> Option<Utf8PathBuf> {
+        self.license_file.as_ref().map(|file| {
+            self.manifest_path
+                .parent()
+                .unwrap_or(&self.manifest_path)
+                .join(file)
+        })
+    }
+
+    /// Full path to the readme file if one is present in the manifest
+    pub fn readme(&self) -> Option<Utf8PathBuf> {
+        self.readme
+            .as_ref()
+            .map(|file| self.manifest_path.join(file))
+    }
+}
+
+/// The source of a package such as crates.io.
+#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq)]
+#[serde(transparent)]
+pub struct Source {
+    /// The underlying string representation of a source.
+    pub repr: String,
+}
+
+impl Source {
+    /// Returns true if the source is crates.io.
+    pub fn is_crates_io(&self) -> bool {
+        self.repr == "registry+https://github.com/rust-lang/crates.io-index"
+    }
+}
+
+impl std::fmt::Display for Source {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        fmt::Display::fmt(&self.repr, f)
+    }
+}
+
+#[derive(Clone, Serialize, Deserialize, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+#[non_exhaustive]
+/// A single target (lib, bin, example, ...) provided by a crate
+pub struct Target {
+    /// Name as given in the `Cargo.toml` or generated from the file name
+    pub name: String,
+    /// Kind of target ("bin", "example", "test", "bench", "lib")
+    pub kind: Vec<String>,
+    /// Almost the same as `kind`, except when an example is a library instead of an executable.
+    /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example`
+    #[serde(default)]
+    #[cfg_attr(feature = "builder", builder(default))]
+    pub crate_types: Vec<String>,
+
+    #[serde(default)]
+    #[cfg_attr(feature = "builder", builder(default))]
+    #[serde(rename = "required-features")]
+    /// This target is built only if these features are enabled.
+    /// It doesn't apply to `lib` targets.
+    pub required_features: Vec<String>,
+    /// Path to the main source file of the target
+    pub src_path: Utf8PathBuf,
+    /// Rust edition for this target
+    #[serde(default = "edition_default")]
+    #[cfg_attr(feature = "builder", builder(default = "edition_default()"))]
+    pub edition: String,
+    /// Whether or not this target has doc tests enabled, and the target is
+    /// compatible with doc testing.
+    ///
+    /// This is always `true` if running with a version of Cargo older than 1.37.
+    #[serde(default = "default_true")]
+    #[cfg_attr(feature = "builder", builder(default = "true"))]
+    pub doctest: bool,
+    /// Whether or not this target is tested by default by `cargo test`.
+    ///
+    /// This is always `true` if running with a version of Cargo older than 1.47.
+    #[serde(default = "default_true")]
+    #[cfg_attr(feature = "builder", builder(default = "true"))]
+    pub test: bool,
+    /// Whether or not this target is documented by `cargo doc`.
+    ///
+    /// This is always `true` if running with a version of Cargo older than 1.50.
+    #[serde(default = "default_true")]
+    #[cfg_attr(feature = "builder", builder(default = "true"))]
+    pub doc: bool,
+}
+
+fn default_true() -> bool {
+    true
+}
+
+fn edition_default() -> String {
+    "2015".to_string()
+}
+
+/// Cargo features flags
+#[derive(Debug, Clone)]
+pub enum CargoOpt {
+    /// Run cargo with `--features-all`
+    AllFeatures,
+    /// Run cargo with `--no-default-features`
+    NoDefaultFeatures,
+    /// Run cargo with `--features <FEATURES>`
+    SomeFeatures(Vec<String>),
+}
+
+/// A builder for configurating `cargo metadata` invocation.
+#[derive(Debug, Clone, Default)]
+pub struct MetadataCommand {
+    /// Path to `cargo` executable.  If not set, this will use the
+    /// the `$CARGO` environment variable, and if that is not set, will
+    /// simply be `cargo`.
+    cargo_path: Option<PathBuf>,
+    /// Path to `Cargo.toml`
+    manifest_path: Option<PathBuf>,
+    /// Current directory of the `cargo metadata` process.
+    current_dir: Option<PathBuf>,
+    /// Output information only about the root package and don't fetch dependencies.
+    no_deps: bool,
+    /// Collections of `CargoOpt::SomeFeatures(..)`
+    features: Vec<String>,
+    /// Latched `CargoOpt::AllFeatures`
+    all_features: bool,
+    /// Latched `CargoOpt::NoDefaultFeatures`
+    no_default_features: bool,
+    /// Arbitrary command line flags to pass to `cargo`.  These will be added
+    /// to the end of the command line invocation.
+    other_options: Vec<String>,
+}
+
+impl MetadataCommand {
+    /// Creates a default `cargo metadata` command, which will look for
+    /// `Cargo.toml` in the ancestors of the current directory.
+    pub fn new() -> MetadataCommand {
+        MetadataCommand::default()
+    }
+    /// Path to `cargo` executable.  If not set, this will use the
+    /// the `$CARGO` environment variable, and if that is not set, will
+    /// simply be `cargo`.
+    pub fn cargo_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
+        self.cargo_path = Some(path.into());
+        self
+    }
+    /// Path to `Cargo.toml`
+    pub fn manifest_path(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
+        self.manifest_path = Some(path.into());
+        self
+    }
+    /// Current directory of the `cargo metadata` process.
+    pub fn current_dir(&mut self, path: impl Into<PathBuf>) -> &mut MetadataCommand {
+        self.current_dir = Some(path.into());
+        self
+    }
+    /// Output information only about the root package and don't fetch dependencies.
+    pub fn no_deps(&mut self) -> &mut MetadataCommand {
+        self.no_deps = true;
+        self
+    }
+    /// Which features to include.
+    ///
+    /// Call this multiple times to specify advanced feature configurations:
+    ///
+    /// ```no_run
+    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
+    /// MetadataCommand::new()
+    ///     .features(CargoOpt::NoDefaultFeatures)
+    ///     .features(CargoOpt::SomeFeatures(vec!["feat1".into(), "feat2".into()]))
+    ///     .features(CargoOpt::SomeFeatures(vec!["feat3".into()]))
+    ///     // ...
+    ///     # ;
+    /// ```
+    ///
+    /// # Panics
+    ///
+    /// `cargo metadata` rejects multiple `--no-default-features` flags. Similarly, the `features()`
+    /// method panics when specifying multiple `CargoOpt::NoDefaultFeatures`:
+    ///
+    /// ```should_panic
+    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
+    /// MetadataCommand::new()
+    ///     .features(CargoOpt::NoDefaultFeatures)
+    ///     .features(CargoOpt::NoDefaultFeatures) // <-- panic!
+    ///     // ...
+    ///     # ;
+    /// ```
+    ///
+    /// The method also panics for multiple `CargoOpt::AllFeatures` arguments:
+    ///
+    /// ```should_panic
+    /// # use cargo_metadata::{CargoOpt, MetadataCommand};
+    /// MetadataCommand::new()
+    ///     .features(CargoOpt::AllFeatures)
+    ///     .features(CargoOpt::AllFeatures) // <-- panic!
+    ///     // ...
+    ///     # ;
+    /// ```
+    pub fn features(&mut self, features: CargoOpt) -> &mut MetadataCommand {
+        match features {
+            CargoOpt::SomeFeatures(features) => self.features.extend(features),
+            CargoOpt::NoDefaultFeatures => {
+                assert!(
+                    !self.no_default_features,
+                    "Do not supply CargoOpt::NoDefaultFeatures more than once!"
+                );
+                self.no_default_features = true;
+            }
+            CargoOpt::AllFeatures => {
+                assert!(
+                    !self.all_features,
+                    "Do not supply CargoOpt::AllFeatures more than once!"
+                );
+                self.all_features = true;
+            }
+        }
+        self
+    }
+    /// Arbitrary command line flags to pass to `cargo`.  These will be added
+    /// to the end of the command line invocation.
+    pub fn other_options(&mut self, options: impl Into<Vec<String>>) -> &mut MetadataCommand {
+        self.other_options = options.into();
+        self
+    }
+
+    /// Builds a command for `cargo metadata`.  This is the first
+    /// part of the work of `exec`.
+    pub fn cargo_command(&self) -> Command {
+        let cargo = self
+            .cargo_path
+            .clone()
+            .or_else(|| env::var("CARGO").map(PathBuf::from).ok())
+            .unwrap_or_else(|| PathBuf::from("cargo"));
+        let mut cmd = Command::new(cargo);
+        cmd.args(&["metadata", "--format-version", "1"]);
+
+        if self.no_deps {
+            cmd.arg("--no-deps");
+        }
+
+        if let Some(path) = self.current_dir.as_ref() {
+            cmd.current_dir(path);
+        }
+
+        if !self.features.is_empty() {
+            cmd.arg("--features").arg(self.features.join(","));
+        }
+        if self.all_features {
+            cmd.arg("--all-features");
+        }
+        if self.no_default_features {
+            cmd.arg("--no-default-features");
+        }
+
+        if let Some(manifest_path) = &self.manifest_path {
+            cmd.arg("--manifest-path").arg(manifest_path.as_os_str());
+        }
+        cmd.args(&self.other_options);
+
+        cmd
+    }
+
+    /// Parses `cargo metadata` output.  `data` must have been
+    /// produced by a command built with `cargo_command`.
+    pub fn parse<T: AsRef<str>>(data: T) -> Result<Metadata> {
+        let meta = serde_json::from_str(data.as_ref())?;
+        Ok(meta)
+    }
+
+    /// Runs configured `cargo metadata` and returns parsed `Metadata`.
+    pub fn exec(&self) -> Result<Metadata> {
+        let output = self.cargo_command().output()?;
+        if !output.status.success() {
+            return Err(Error::CargoMetadata {
+                stderr: String::from_utf8(output.stderr)?,
+            });
+        }
+        let stdout = from_utf8(&output.stdout)?
+            .lines()
+            .find(|line| line.starts_with('{'))
+            .ok_or_else(|| Error::NoJson)?;
+        Self::parse(stdout)
+    }
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs b/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs
new file mode 100644
index 0000000..a52cde1
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/src/messages.rs
@@ -0,0 +1,165 @@
+use super::{Diagnostic, PackageId, Target};
+use camino::Utf8PathBuf;
+#[cfg(feature = "builder")]
+use derive_builder::Builder;
+use serde::{Deserialize, Serialize};
+use std::fmt;
+use std::io::{self, BufRead, Lines, Read};
+
+/// Profile settings used to determine which compiler flags to use for a
+/// target.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct ArtifactProfile {
+    /// Optimization level. Possible values are 0-3, s or z.
+    pub opt_level: String,
+    /// The amount of debug info. 0 for none, 1 for limited, 2 for full
+    pub debuginfo: Option<u32>,
+    /// State of the `cfg(debug_assertions)` directive, enabling macros like
+    /// `debug_assert!`
+    pub debug_assertions: bool,
+    /// State of the overflow checks.
+    pub overflow_checks: bool,
+    /// Whether this profile is a test
+    pub test: bool,
+}
+
+/// A compiler-generated file.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct Artifact {
+    /// The package this artifact belongs to
+    pub package_id: PackageId,
+    /// The target this artifact was compiled for
+    pub target: Target,
+    /// The profile this artifact was compiled with
+    pub profile: ArtifactProfile,
+    /// The enabled features for this artifact
+    pub features: Vec<String>,
+    /// The full paths to the generated artifacts
+    /// (e.g. binary file and separate debug info)
+    pub filenames: Vec<Utf8PathBuf>,
+    /// Path to the executable file
+    pub executable: Option<Utf8PathBuf>,
+    /// If true, then the files were already generated
+    pub fresh: bool,
+}
+
+/// Message left by the compiler
+// TODO: Better name. This one comes from machine_message.rs
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct CompilerMessage {
+    /// The package this message belongs to
+    pub package_id: PackageId,
+    /// The target this message is aimed at
+    pub target: Target,
+    /// The message the compiler sent.
+    pub message: Diagnostic,
+}
+
+/// Output of a build script execution.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct BuildScript {
+    /// The package this build script execution belongs to
+    pub package_id: PackageId,
+    /// The libs to link
+    pub linked_libs: Vec<Utf8PathBuf>,
+    /// The paths to search when resolving libs
+    pub linked_paths: Vec<Utf8PathBuf>,
+    /// Various `--cfg` flags to pass to the compiler
+    pub cfgs: Vec<String>,
+    /// The environment variables to add to the compilation
+    pub env: Vec<(String, String)>,
+    /// The `OUT_DIR` environment variable where this script places its output
+    ///
+    /// Added in Rust 1.41.
+    #[serde(default)]
+    pub out_dir: Utf8PathBuf,
+}
+
+/// Final result of a build.
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "builder", derive(Builder))]
+#[non_exhaustive]
+#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
+pub struct BuildFinished {
+    /// Whether or not the build finished successfully.
+    pub success: bool,
+}
+
+/// A cargo message
+#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
+#[non_exhaustive]
+#[serde(tag = "reason", rename_all = "kebab-case")]
+pub enum Message {
+    /// The compiler generated an artifact
+    CompilerArtifact(Artifact),
+    /// The compiler wants to display a message
+    CompilerMessage(CompilerMessage),
+    /// A build script successfully executed.
+    BuildScriptExecuted(BuildScript),
+    /// The build has finished.
+    ///
+    /// This is emitted at the end of the build as the last message.
+    /// Added in Rust 1.44.
+    BuildFinished(BuildFinished),
+    /// A line of text which isn't a cargo or compiler message.
+    /// Line separator is not included
+    #[serde(skip)]
+    TextLine(String),
+}
+
+impl Message {
+    /// Creates an iterator of Message from a Read outputting a stream of JSON
+    /// messages. For usage information, look at the top-level documentation.
+    pub fn parse_stream<R: BufRead>(input: R) -> MessageIter<R> {
+        MessageIter {
+            lines: input.lines(),
+        }
+    }
+}
+
+impl fmt::Display for CompilerMessage {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "{}", self.message)
+    }
+}
+
+/// An iterator of Messages.
+pub struct MessageIter<R> {
+    lines: Lines<R>,
+}
+
+impl<R: BufRead> Iterator for MessageIter<R> {
+    type Item = io::Result<Message>;
+    fn next(&mut self) -> Option<Self::Item> {
+        let line = self.lines.next()?;
+        let message = line.map(|it| {
+            let mut deserializer = serde_json::Deserializer::from_str(&it);
+            deserializer.disable_recursion_limit();
+            Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(it))
+        });
+        Some(message)
+    }
+}
+
+/// An iterator of Message.
+type MessageIterator<R> =
+    serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>;
+
+/// Creates an iterator of Message from a Read outputting a stream of JSON
+/// messages. For usage information, look at the top-level documentation.
+#[deprecated(note = "Use Message::parse_stream instead")]
+pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
+    serde_json::Deserializer::from_reader(input).into_iter::<Message>()
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs b/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs
new file mode 100644
index 0000000..70b131b
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/tests/selftest.rs
@@ -0,0 +1,159 @@
+use std::env::current_dir;
+use std::path::PathBuf;
+
+use semver::Version;
+
+use cargo_metadata::{CargoOpt, Error, MetadataCommand};
+use serde::Deserialize;
+
+#[derive(Debug, PartialEq, Eq, Deserialize)]
+struct TestPackageMetadata {
+    some_field: bool,
+    other_field: String,
+}
+
+#[test]
+fn metadata() {
+    let metadata = MetadataCommand::new().no_deps().exec().unwrap();
+
+    let this = &metadata.packages[0];
+    assert_eq!(this.name, "cargo_metadata");
+    assert_eq!(this.targets.len(), 3);
+
+    let lib = this
+        .targets
+        .iter()
+        .find(|t| t.name == "cargo_metadata")
+        .unwrap();
+    assert_eq!(lib.kind[0], "lib");
+    assert_eq!(lib.crate_types[0], "lib");
+
+    let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap();
+    assert_eq!(selftest.name, "selftest");
+    assert_eq!(selftest.kind[0], "test");
+    assert_eq!(selftest.crate_types[0], "bin");
+
+    let package_metadata = &metadata.packages[0]
+        .metadata
+        .as_object()
+        .expect("package.metadata must be a table.");
+    assert_eq!(package_metadata.len(), 1);
+
+    let value = package_metadata.get("cargo_metadata_test").unwrap();
+    let test_package_metadata: TestPackageMetadata = serde_json::from_value(value.clone()).unwrap();
+    assert_eq!(
+        test_package_metadata,
+        TestPackageMetadata {
+            some_field: true,
+            other_field: "foo".into(),
+        }
+    );
+}
+
+#[test]
+fn builder_interface() {
+    let _ = MetadataCommand::new()
+        .manifest_path("Cargo.toml")
+        .exec()
+        .unwrap();
+    let _ = MetadataCommand::new()
+        .manifest_path(String::from("Cargo.toml"))
+        .exec()
+        .unwrap();
+    let _ = MetadataCommand::new()
+        .manifest_path(PathBuf::from("Cargo.toml"))
+        .exec()
+        .unwrap();
+    let _ = MetadataCommand::new()
+        .manifest_path("Cargo.toml")
+        .no_deps()
+        .exec()
+        .unwrap();
+    let _ = MetadataCommand::new()
+        .manifest_path("Cargo.toml")
+        .features(CargoOpt::AllFeatures)
+        .exec()
+        .unwrap();
+    let _ = MetadataCommand::new()
+        .manifest_path("Cargo.toml")
+        .current_dir(current_dir().unwrap())
+        .exec()
+        .unwrap();
+}
+
+#[test]
+fn error1() {
+    match MetadataCommand::new().manifest_path("foo").exec() {
+        Err(Error::CargoMetadata { stderr }) => assert_eq!(
+            stderr.trim(),
+            "error: the manifest-path must be a path to a Cargo.toml file"
+        ),
+        _ => unreachable!(),
+    }
+}
+
+#[test]
+fn error2() {
+    match MetadataCommand::new()
+        .manifest_path("foo/Cargo.toml")
+        .exec()
+    {
+        Err(Error::CargoMetadata { stderr }) => assert_eq!(
+            stderr.trim(),
+            "error: manifest path `foo/Cargo.toml` does not exist"
+        ),
+        _ => unreachable!(),
+    }
+}
+
+#[test]
+fn cargo_path() {
+    match MetadataCommand::new()
+        .cargo_path("this does not exist")
+        .exec()
+    {
+        Err(Error::Io(e)) => assert_eq!(e.kind(), std::io::ErrorKind::NotFound),
+        _ => unreachable!(),
+    }
+}
+
+#[test]
+fn metadata_deps() {
+    std::env::set_var("CARGO_PROFILE", "3");
+    let metadata = MetadataCommand::new()
+        .manifest_path("Cargo.toml")
+        .exec()
+        .unwrap();
+    let this_id = metadata
+        .workspace_members
+        .first()
+        .expect("Did not find ourselves");
+    let this = &metadata[this_id];
+
+    assert_eq!(this.name, "cargo_metadata");
+
+    let lib = this
+        .targets
+        .iter()
+        .find(|t| t.name == "cargo_metadata")
+        .unwrap();
+    assert_eq!(lib.kind[0], "lib");
+    assert_eq!(lib.crate_types[0], "lib");
+
+    let selftest = this.targets.iter().find(|t| t.name == "selftest").unwrap();
+    assert_eq!(selftest.name, "selftest");
+    assert_eq!(selftest.kind[0], "test");
+    assert_eq!(selftest.crate_types[0], "bin");
+
+    let dependencies = &this.dependencies;
+
+    let serde = dependencies
+        .iter()
+        .find(|dep| dep.name == "serde")
+        .expect("Did not find serde dependency");
+
+    assert_eq!(serde.kind, cargo_metadata::DependencyKind::Normal);
+    assert!(!serde.req.matches(&Version::parse("1.0.0").unwrap()));
+    assert!(serde.req.matches(&Version::parse("1.99.99").unwrap()));
+    assert!(!serde.req.matches(&Version::parse("2.0.0").unwrap()));
+}
diff --git a/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs b/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs
new file mode 100644
index 0000000..f899e6d
--- /dev/null
+++ b/third_party/rust/cargo_metadata/v0_14/crate/tests/test_samples.rs
@@ -0,0 +1,624 @@
+extern crate cargo_metadata;
+extern crate semver;
+#[macro_use]
+extern crate serde_json;
+
+use camino::Utf8PathBuf;
+use cargo_metadata::{CargoOpt, DependencyKind, Metadata, MetadataCommand};
+
+#[test]
+fn old_minimal() {
+    // Output from oldest supported version (1.24).
+    // This intentionally has as many null fields as possible.
+    // 1.8 is when metadata was introduced.
+    // Older versions not supported because the following are required:
+    // - `workspace_members` added in 1.13
+    // - `target_directory` added in 1.19
+    // - `workspace_root` added in 1.24
+    let json = r#"
+{
+  "packages": [
+    {
+      "name": "foo",
+      "version": "0.1.0",
+      "id": "foo 0.1.0 (path+file:///foo)",
+      "license": null,
+      "license_file": null,
+      "description": null,
+      "source": null,
+      "dependencies": [
+        {
+          "name": "somedep",
+          "source": null,
+          "req": "^1.0",
+          "kind": null,
+          "optional": false,
+          "uses_default_features": true,
+          "features": [],
+          "target": null
+        }
+      ],
+      "targets": [
+        {
+          "kind": [
+            "bin"
+          ],
+          "crate_types": [
+            "bin"
+          ],
+          "name": "foo",
+          "src_path": "/foo/src/main.rs"
+        }
+      ],
+      "features": {},
+      "manifest_path": "/foo/Cargo.toml"
+    }
+  ],
+  "workspace_members": [
+    "foo 0.1.0 (path+file:///foo)"
+  ],
+  "resolve": null,
+  "target_directory": "/foo/target",
+  "version": 1,
+  "workspace_root": "/foo"
+}
+"#;
+    let meta: Metadata = serde_json::from_str(json).unwrap();
+    assert_eq!(meta.packages.len(), 1);
+    let pkg = &meta.packages[0];
+    assert_eq!(pkg.name, "foo");
+    assert_eq!(pkg.version, semver::Version::parse("0.1.0").unwrap());
+    assert_eq!(pkg.authors.len(), 0);
+    assert_eq!(pkg.id.to_string(), "foo 0.1.0 (path+file:///foo)");
+    assert_eq!(pkg.description, None);
+    assert_eq!(pkg.license, None);
+    assert_eq!(pkg.license_file, None);
+    assert_eq!(pkg.default_run, None);
+    assert_eq!(pkg.rust_version, None);
+    assert_eq!(pkg.dependencies.len(), 1);
+    let dep = &pkg.dependencies[0];
+    assert_eq!(dep.name, "somedep");
+    assert_eq!(dep.source, None);
+    assert_eq!(dep.req, semver::VersionReq::parse("^1.0").unwrap());
+    assert_eq!(dep.kind, DependencyKind::Normal);
+    assert_eq!(dep.optional, false);
+    assert_eq!(dep.uses_default_features, true);
+    assert_eq!(dep.features.len(), 0);
+    assert!(dep.target.is_none());
+    assert_eq!(dep.rename, None);
+    assert_eq!(dep.registry, None);
+    assert_eq!(pkg.targets.len(), 1);
+    let target = &pkg.targets[0];
+    assert_eq!(target.name, "foo");
+    assert_eq!(target.kind, vec!["bin"]);
+    assert_eq!(target.crate_types, vec!["bin"]);
+    assert_eq!(target.required_features.len(), 0);
+    assert_eq!(target.src_path, "/foo/src/main.rs");
+    assert_eq!(target.edition, "2015");
+    assert_eq!(target.doctest, true);
+    assert_eq!(target.test, true);
+    assert_eq!(target.doc, true);
+    assert_eq!(pkg.features.len(), 0);
+    assert_eq!(pkg.manifest_path, "/foo/Cargo.toml");
+    assert_eq!(pkg.categories.len(), 0);
+    assert_eq!(pkg.keywords.len(), 0);
+    assert_eq!(pkg.readme, None);
+    assert_eq!(pkg.repository, None);
+    assert_eq!(pkg.homepage, None);
+    assert_eq!(pkg.documentation, None);
+    assert_eq!(pkg.edition, "2015");
+    assert_eq!(pkg.metadata, serde_json::Value::Null);
+    assert_eq!(pkg.links, None);
+    assert_eq!(pkg.publish, None);
+    assert_eq!(meta.workspace_members.len(), 1);
+    assert_eq!(
+        meta.workspace_members[0].to_string(),
+        "foo 0.1.0 (path+file:///foo)"
+    );
+    assert!(meta.resolve.is_none());
+    assert_eq!(meta.workspace_root, "/foo");
+    assert_eq!(meta.workspace_metadata, serde_json::Value::Null);
+    assert_eq!(meta.target_directory, "/foo/target");
+}
+
+macro_rules! sorted {
+    ($e:expr) => {{
+        let mut v = $e.clone();
+        v.sort();
+        v
+    }};
+}
+
+fn cargo_version() -> semver::Version {
+    let output = std::process::Command::new("cargo")
+        .arg("-V")
+        .output()
+        .expect("Failed to exec cargo.");
+    let out = std::str::from_utf8(&output.stdout)
+        .expect("invalid utf8")
+        .trim();
+    let split: Vec<&str> = out.split_whitespace().collect();
+    assert!(split.len() >= 2, "cargo -V output is unexpected: {}", out);
+    let mut ver = semver::Version::parse(split[1]).expect("cargo -V semver could not be parsed");
+    // Don't care about metadata, it is awkward to compare.
+    ver.pre = semver::Prerelease::EMPTY;
+    ver.build = semver::BuildMetadata::EMPTY;
+    ver
+}
+
+#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
+struct WorkspaceMetadata {
+    testobject: TestObject,
+}
+
+#[derive(serde::Deserialize, PartialEq, Eq, Debug)]
+struct TestObject {
+    myvalue: String,
+}
+
+#[test]
+fn all_the_fields() {
+    // All the fields currently generated as of 1.60. This tries to exercise as
+    // much as possible.
+    let ver = cargo_version();
+    let minimum = semver::Version::parse("1.56.0").unwrap();
+    if ver < minimum {
+        // edition added in 1.30
+        // rename added in 1.31
+        // links added in 1.33
+        // doctest added in 1.37
+        // publish added in 1.39
+        // dep_kinds added in 1.41
+        // test added in 1.47
+        // homepage added in 1.49
+        // documentation added in 1.49
+        // doc added in 1.50
+        // path added in 1.51
+        // default_run added in 1.55
+        // rust_version added in 1.58
+        eprintln!("Skipping all_the_fields test, cargo {} is too old.", ver);
+        return;
+    }
+    let meta = MetadataCommand::new()
+        .manifest_path("tests/all/Cargo.toml")
+        .exec()
+        .unwrap();
+    assert_eq!(meta.workspace_root.file_name().unwrap(), "all");
+    assert_eq!(
+        serde_json::from_value::<WorkspaceMetadata>(meta.workspace_metadata).unwrap(),
+        WorkspaceMetadata {
+            testobject: TestObject {
+                myvalue: "abc".to_string()
+            }
+        }
+    );
+    assert_eq!(meta.workspace_members.len(), 1);
+    assert!(meta.workspace_members[0].to_string().starts_with("all"));
+
+    assert_eq!(meta.packages.len(), 9);
+    let all = meta.packages.iter().find(|p| p.name == "all").unwrap();
+    assert_eq!(all.version, semver::Version::parse("0.1.0").unwrap());
+    assert_eq!(all.authors, vec!["Jane Doe <user@example.com>"]);
+    assert!(all.id.to_string().starts_with("all"));
+    assert_eq!(all.description, Some("Package description.".to_string()));
+    assert_eq!(all.license, Some("MIT/Apache-2.0".to_string()));
+    assert_eq!(all.license_file, Some(Utf8PathBuf::from("LICENSE")));
+    assert!(all.license_file().unwrap().ends_with("tests/all/LICENSE"));
+    assert_eq!(all.publish, Some(vec![]));
+    assert_eq!(all.links, Some("foo".to_string()));
+    assert_eq!(all.default_run, Some("otherbin".to_string()));
+    if ver >= semver::Version::parse("1.58.0").unwrap() {
+        assert_eq!(
+            all.rust_version,
+            Some(semver::VersionReq::parse("1.56").unwrap())
+        );
+    }
+
+    assert_eq!(all.dependencies.len(), 8);
+    let bitflags = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "bitflags")
+        .unwrap();
+    assert_eq!(
+        bitflags.source,
+        Some("registry+https://github.com/rust-lang/crates.io-index".to_string())
+    );
+    assert_eq!(bitflags.optional, true);
+    assert_eq!(bitflags.req, semver::VersionReq::parse("^1.0").unwrap());
+
+    let path_dep = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "path-dep")
+        .unwrap();
+    assert_eq!(path_dep.source, None);
+    assert_eq!(path_dep.kind, DependencyKind::Normal);
+    assert_eq!(path_dep.req, semver::VersionReq::parse("*").unwrap());
+    assert_eq!(
+        path_dep.path.as_ref().map(|p| p.ends_with("path-dep")),
+        Some(true),
+    );
+
+    all.dependencies
+        .iter()
+        .find(|d| d.name == "namedep")
+        .unwrap();
+
+    let featdep = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "featdep")
+        .unwrap();
+    assert_eq!(featdep.features, vec!["i128"]);
+    assert_eq!(featdep.uses_default_features, false);
+
+    let renamed = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "oldname")
+        .unwrap();
+    assert_eq!(renamed.rename, Some("newname".to_string()));
+
+    let devdep = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "devdep")
+        .unwrap();
+    assert_eq!(devdep.kind, DependencyKind::Development);
+
+    let bdep = all.dependencies.iter().find(|d| d.name == "bdep").unwrap();
+    assert_eq!(bdep.kind, DependencyKind::Build);
+
+    let windep = all
+        .dependencies
+        .iter()
+        .find(|d| d.name == "windep")
+        .unwrap();
+    assert_eq!(
+        windep.target.as_ref().map(|x| x.to_string()),
+        Some("cfg(windows)".to_string())
+    );
+
+    macro_rules! get_file_name {
+        ($v:expr) => {
+            all.targets
+                .iter()
+                .find(|t| t.src_path.file_name().unwrap() == $v)
+                .unwrap()
+        };
+    }
+    assert_eq!(all.targets.len(), 8);
+    let lib = get_file_name!("lib.rs");
+    assert_eq!(lib.name, "all");
+    assert_eq!(sorted!(lib.kind), vec!["cdylib", "rlib", "staticlib"]);
+    assert_eq!(
+        sorted!(lib.crate_types),
+        vec!["cdylib", "rlib", "staticlib"]
+    );
+    assert_eq!(lib.required_features.len(), 0);
+    assert_eq!(lib.edition, "2018");
+    assert_eq!(lib.doctest, true);
+    assert_eq!(lib.test, true);
+    assert_eq!(lib.doc, true);
+
+    let main = get_file_name!("main.rs");
+    assert_eq!(main.crate_types, vec!["bin"]);
+    assert_eq!(main.kind, vec!["bin"]);
+    assert_eq!(main.doctest, false);
+    assert_eq!(main.test, true);
+    assert_eq!(main.doc, true);
+
+    let otherbin = get_file_name!("otherbin.rs");
+    assert_eq!(otherbin.edition, "2015");
+    assert_eq!(otherbin.doc, false);
+
+    let reqfeat = get_file_name!("reqfeat.rs");
+    assert_eq!(reqfeat.required_features, vec!["feat2"]);
+
+    let ex1 = get_file_name!("ex1.rs");
+    assert_eq!(ex1.kind, vec!["example"]);
+    assert_eq!(ex1.test, false);
+
+    let t1 = get_file_name!("t1.rs");
+    assert_eq!(t1.kind, vec!["test"]);
+
+    let b1 = get_file_name!("b1.rs");
+    assert_eq!(b1.kind, vec!["bench"]);
+
+    let build = get_file_name!("build.rs");
+    assert_eq!(build.kind, vec!["custom-build"]);
+
+    if ver >= semver::Version::parse("1.60.0").unwrap() {
+        // 1.60 now reports optional dependencies within the features table
+        assert_eq!(all.features.len(), 4);
+        assert_eq!(all.features["bitflags"], vec!["dep:bitflags"]);
+    } else {
+        assert_eq!(all.features.len(), 3);
+    }
+    assert_eq!(all.features["feat1"].len(), 0);
+    assert_eq!(all.features["feat2"].len(), 0);
+    assert_eq!(sorted!(all.features["default"]), vec!["bitflags", "feat1"]);
+
+    assert!(all.manifest_path.ends_with("all/Cargo.toml"));
+    assert_eq!(all.categories, vec!["command-line-utilities"]);
+    assert_eq!(all.keywords, vec!["cli"]);
+    assert_eq!(all.readme, Some(Utf8PathBuf::from("README.md")));
+    assert_eq!(
+        all.repository,
+        Some("https://github.com/oli-obk/cargo_metadata/".to_string())
+    );
+    assert_eq!(
+        all.homepage,
+        Some("https://github.com/oli-obk/cargo_metadata/".to_string())
+    );
+    assert_eq!(
+        all.documentation,
+        Some("https://docs.rs/cargo_metadata/".to_string())
+    );
+    assert_eq!(all.edition, "2018");
+    assert_eq!(
+        all.metadata,
+        json!({
+            "docs": {
+                "rs": {
+                    "all-features": true,
+                    "default-target": "x86_64-unknown-linux-gnu",
+                    "rustc-args": ["--example-rustc-arg"]
+                }
+            }
+        })
+    );
+
+    let resolve = meta.resolve.as_ref().unwrap();
+    assert!(resolve
+        .root
+        .as_ref()
+        .unwrap()
+        .to_string()
+        .starts_with("all"));
+
+    assert_eq!(resolve.nodes.len(), 9);
+    let path_dep = resolve
+        .nodes
+        .iter()
+        .find(|n| n.id.to_string().starts_with("path-dep"))
+        .unwrap();
+    assert_eq!(path_dep.deps.len(), 0);
+    assert_eq!(path_dep.dependencies.len(), 0);
+    assert_eq!(path_dep.features.len(), 0);
+
+    let bitflags = resolve
+        .nodes
+        .iter()
+        .find(|n| n.id.to_string().starts_with("bitflags"))
+        .unwrap();
+    assert_eq!(bitflags.features, vec!["default"]);
+
+    let featdep = resolve
+        .nodes
+        .iter()
+        .find(|n| n.id.to_string().starts_with("featdep"))
+        .unwrap();
+    assert_eq!(featdep.features, vec!["i128"]);
+
+    let all = resolve
+        .nodes
+        .iter()
+        .find(|n| n.id.to_string().starts_with("all"))
+        .unwrap();
+    assert_eq!(all.dependencies.len(), 8);
+    assert_eq!(all.deps.len(), 8);
+    let newname = all.deps.iter().find(|d| d.name == "newname").unwrap();
+    assert!(newname.pkg.to_string().starts_with("oldname"));
+    // Note the underscore here.
+    let path_dep = all.deps.iter().find(|d| d.name == "path_dep").unwrap();
+    assert!(path_dep.pkg.to_string().starts_with("path-dep"));
+    assert_eq!(path_dep.dep_kinds.len(), 1);
+    let kind = &path_dep.dep_kinds[0];
+    assert_eq!(kind.kind, DependencyKind::Normal);
+    assert!(kind.target.is_none());
+
+    let namedep = all
+        .deps
+        .iter()
+        .find(|d| d.name == "different_name")
+        .unwrap();
+    assert!(namedep.pkg.to_string().starts_with("namedep"));
+    assert_eq!(sorted!(all.features), vec!["bitflags", "default", "feat1"]);
+
+    let bdep = all.deps.iter().find(|d| d.name == "bdep").unwrap();
+    assert_eq!(bdep.dep_kinds.len(), 1);
+    let kind = &bdep.dep_kinds[0];
+    assert_eq!(kind.kind, DependencyKind::Build);
+    assert!(kind.target.is_none());
+
+    let devdep = all.deps.iter().find(|d| d.name == "devdep").unwrap();
+    assert_eq!(devdep.dep_kinds.len(), 1);
+    let kind = &devdep.dep_kinds[0];
+    assert_eq!(kind.kind, DependencyKind::Development);
+    assert!(kind.target.is_none());
+
+    let windep = all.deps.iter().find(|d| d.name == "windep").unwrap();
+    assert_eq!(windep.dep_kinds.len(), 1);
+    let kind = &windep.dep_kinds[0];
+    assert_eq!(kind.kind, DependencyKind::Normal);
+    assert_eq!(
+        kind.target.as_ref().map(|x| x.to_string()),
+        Some("cfg(windows)".to_string())
+    );
+}
+
+#[test]
+fn alt_registry() {
+    // This is difficult to test (would need to set up a custom index).
+    // Just manually check the JSON is handled.
+    let json = r#"
+{
+  "packages": [
+    {
+      "name": "alt",
+      "version": "0.1.0",
+      "id": "alt 0.1.0 (path+file:///alt)",
+      "source": null,
+      "dependencies": [
+        {
+          "name": "alt2",
+          "source": "registry+https://example.com",
+          "req": "^0.1",
+          "kind": null,
+          "rename": null,
+          "optional": false,
+          "uses_default_features": true,
+          "features": [],
+          "target": null,
+          "registry": "https://example.com"
+        }
+      ],
+      "targets": [
+        {
+          "kind": [
+            "lib"
+          ],
+          "crate_types": [
+            "lib"
+          ],
+          "name": "alt",
+          "src_path": "/alt/src/lib.rs",
+          "edition": "2018"
+        }
+      ],
+      "features": {},
+      "manifest_path": "/alt/Cargo.toml",
+      "metadata": null,
+      "authors": [],
+      "categories": [],
+      "keywords": [],
+      "readme": null,
+      "repository": null,
+      "edition": "2018",
+      "links": null
+    }
+  ],
+  "workspace_members": [
+    "alt 0.1.0 (path+file:///alt)"
+  ],
+  "resolve": null,
+  "target_directory": "/alt/target",
+  "version": 1,
+  "workspace_root": "/alt"
+}
+"#;
+    let meta: Metadata = serde_json::from_str(json).unwrap();
+    assert_eq!(meta.packages.len(), 1);
+    let alt = &meta.packages[0];
+    let deps = &alt.dependencies;
+    assert_eq!(deps.len(), 1);
+    let dep = &deps[0];
+    assert_eq!(dep.registry, Some("https://example.com".to_string()));
+}
+
+#[test]
+fn current_dir() {
+    let meta = MetadataCommand::new()
+        .current_dir("tests/all/namedep")
+        .exec()
+        .unwrap();
+    let namedep = meta.packages.iter().find(|p| p.name == "namedep").unwrap();
+    assert!(namedep.name.starts_with("namedep"));
+}
+
+#[test]
+fn parse_stream_is_robust() {
+    // Proc macros can print stuff to stdout, which naturally breaks JSON messages.
+    // Let's check that we don't die horribly in this case, and report an error.
+    let json_output = r##"{"reason":"compiler-artifact","package_id":"chatty 0.1.0 (path+file:///chatty-macro/chatty)","target":{"kind":["proc-macro"],"crate_types":["proc-macro"],"name":"chatty","src_path":"/chatty-macro/chatty/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/deps/libchatty-f2adcff24cdf3bb2.so"],"executable":null,"fresh":false}
+Evil proc macro was here!
+{"reason":"compiler-artifact","package_id":"chatty-macro 0.1.0 (path+file:///chatty-macro)","target":{"kind":["lib"],"crate_types":["lib"],"name":"chatty-macro","src_path":"/chatty-macro/src/lib.rs","edition":"2018","doctest":true},"profile":{"opt_level":"0","debuginfo":2,"debug_assertions":true,"overflow_checks":true,"test":false},"features":[],"filenames":["/chatty-macro/target/debug/libchatty_macro.rlib","/chatty-macro/target/debug/deps/libchatty_macro-cb5956ed52a11fb6.rmeta"],"executable":null,"fresh":false}
+"##;
+    let mut n_messages = 0;
+    let mut text = String::new();
+    for message in cargo_metadata::Message::parse_stream(json_output.as_bytes()) {
+        let message = message.unwrap();
+        match message {
+            cargo_metadata::Message::TextLine(line) => text = line,
+            _ => n_messages += 1,
+        }
+    }
+    assert_eq!(n_messages, 2);
+    assert_eq!(text, "Evil proc macro was here!");
+}
+
+#[test]
+fn advanced_feature_configuration() {
+    fn build_features<F: FnOnce(&mut MetadataCommand) -> &mut MetadataCommand>(
+        func: F,
+    ) -> Vec<String> {
+        let mut meta = MetadataCommand::new();
+        let meta = meta.manifest_path("tests/all/Cargo.toml");
+
+        let meta = func(meta);
+        let meta = meta.exec().unwrap();
+
+        let resolve = meta.resolve.as_ref().unwrap();
+
+        let all = resolve
+            .nodes
+            .iter()
+            .find(|n| n.id.to_string().starts_with("all"))
+            .unwrap();
+
+        all.features.clone()
+    }
+
+    // Default behavior; tested above
+    let default_features = build_features(|meta| meta);
+    assert_eq!(
+        sorted!(default_features),
+        vec!["bitflags", "default", "feat1"]
+    );
+
+    // Manually specify the same default features
+    let manual_features = build_features(|meta| {
+        meta.features(CargoOpt::NoDefaultFeatures)
+            .features(CargoOpt::SomeFeatures(vec![
+                "feat1".into(),
+                "bitflags".into(),
+            ]))
+    });
+    assert_eq!(sorted!(manual_features), vec!["bitflags", "feat1"]);
+
+    // Multiple SomeFeatures is same as one longer SomeFeatures
+    let manual_features = build_features(|meta| {
+        meta.features(CargoOpt::NoDefaultFeatures)
+            .features(CargoOpt::SomeFeatures(vec!["feat1".into()]))
+            .features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
+    });
+    assert_eq!(sorted!(manual_features), vec!["feat1", "feat2"]);
+
+    // No features + All features == All features
+    let all_features = build_features(|meta| {
+        meta.features(CargoOpt::AllFeatures)
+            .features(CargoOpt::NoDefaultFeatures)
+    });
+    assert_eq!(
+        sorted!(all_features),
+        vec!["bitflags", "default", "feat1", "feat2"]
+    );
+
+    // The '--all-features' flag supersedes other feature flags
+    let all_flag_variants = build_features(|meta| {
+        meta.features(CargoOpt::SomeFeatures(vec!["feat2".into()]))
+            .features(CargoOpt::NoDefaultFeatures)
+            .features(CargoOpt::AllFeatures)
+    });
+    assert_eq!(sorted!(all_flag_variants), sorted!(all_features));
+}
+
+#[test]
+fn depkind_to_string() {
+    assert_eq!(DependencyKind::Normal.to_string(), "normal");
+    assert_eq!(DependencyKind::Development.to_string(), "dev");
+    assert_eq!(DependencyKind::Build.to_string(), "build");
+    assert_eq!(DependencyKind::Unknown.to_string(), "Unknown");
+}
diff --git a/third_party/rust/cargo_platform/v0_1/BUILD.gn b/third_party/rust/cargo_platform/v0_1/BUILD.gn
new file mode 100644
index 0000000..3194458
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2022 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/rust/cargo_crate.gni")
+
+cargo_crate("lib") {
+  crate_name = "cargo_platform"
+  epoch = "0.1"
+  crate_type = "rlib"
+
+  # Only for usage from third-party crates. Add the crate to
+  # third_party.toml to use it from first-party code.
+  visibility = [ "//third_party/rust/*" ]
+  crate_root = "crate/src/lib.rs"
+
+  # Unit tests skipped. Generate with --with-tests to include them.
+  build_native_rust_unit_tests = false
+  sources = [ "crate/src/lib.rs" ]
+  edition = "2018"
+  cargo_pkg_version = "0.1.2"
+  cargo_pkg_authors = "The Cargo Project Developers"
+  cargo_pkg_name = "cargo-platform"
+  cargo_pkg_description = "Cargo's representation of a target platform."
+  deps = [ "//third_party/rust/serde/v1:lib" ]
+}
diff --git a/third_party/rust/cargo_platform/v0_1/README.chromium b/third_party/rust/cargo_platform/v0_1/README.chromium
new file mode 100644
index 0000000..2f362f59
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/README.chromium
@@ -0,0 +1,6 @@
+Name: cargo-platform
+URL: https://crates.io/crates/cargo-platform
+Description: Cargo's representation of a target platform.
+Version: 0.1.2
+Security Critical: no
+License: Apache 2.0
diff --git a/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json b/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json
new file mode 100644
index 0000000..5f45bec
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/.cargo_vcs_info.json
@@ -0,0 +1,5 @@
+{
+  "git": {
+    "sha1": "981508778c4fac545eda4d517b9d6ddf48ed6636"
+  }
+}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock b/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock
new file mode 100644
index 0000000..059f730
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.lock
@@ -0,0 +1,65 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "cargo-platform"
+version = "0.1.2"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
+dependencies = [
+ "unicode-xid",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "serde"
+version = "1.0.127"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.127"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "syn"
+version = "1.0.74"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-xid",
+]
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml
new file mode 100644
index 0000000..ebf12c85
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml
@@ -0,0 +1,24 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "cargo-platform"
+version = "0.1.2"
+authors = ["The Cargo Project Developers"]
+description = "Cargo's representation of a target platform."
+homepage = "https://github.com/rust-lang/cargo"
+documentation = "https://docs.rs/cargo-platform"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/cargo"
+[dependencies.serde]
+version = "1.0.82"
+features = ["derive"]
diff --git a/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig
new file mode 100644
index 0000000..2b5e86e
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/Cargo.toml.orig
@@ -0,0 +1,13 @@
+[package]
+name = "cargo-platform"
+version = "0.1.2"
+authors = ["The Cargo Project Developers"]
+edition = "2018"
+license = "MIT OR Apache-2.0"
+homepage = "https://github.com/rust-lang/cargo"
+repository = "https://github.com/rust-lang/cargo"
+documentation = "https://docs.rs/cargo-platform"
+description = "Cargo's representation of a target platform."
+
+[dependencies]
+serde = { version = "1.0.82", features = ['derive'] }
diff --git a/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE
new file mode 100644
index 0000000..c98d27d
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-APACHE
@@ -0,0 +1,201 @@
+                              Apache License
+                        Version 2.0, January 2004
+                     https://www.apache.org/licenses/LICENSE-2.0
+
+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
+
+	https://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.
diff --git a/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT
new file mode 100644
index 0000000..31aa7938
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/LICENSE-MIT
@@ -0,0 +1,23 @@
+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
+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.
diff --git a/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs b/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs
new file mode 100644
index 0000000..9ad5d10d
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/examples/matches.rs
@@ -0,0 +1,55 @@
+//! This example demonstrates how to filter a Platform based on the current
+//! host target.
+
+use cargo_platform::{Cfg, Platform};
+use std::process::Command;
+use std::str::FromStr;
+
+static EXAMPLES: &[&str] = &[
+    "cfg(windows)",
+    "cfg(unix)",
+    "cfg(target_os=\"macos\")",
+    "cfg(target_os=\"linux\")",
+    "cfg(any(target_arch=\"x86\", target_arch=\"x86_64\"))",
+];
+
+fn main() {
+    let target = get_target();
+    let cfgs = get_cfgs();
+    println!("host target={} cfgs:", target);
+    for cfg in &cfgs {
+        println!("  {}", cfg);
+    }
+    let mut examples: Vec<&str> = EXAMPLES.iter().copied().collect();
+    examples.push(target.as_str());
+    for example in examples {
+        let p = Platform::from_str(example).unwrap();
+        println!("{:?} matches: {:?}", example, p.matches(&target, &cfgs));
+    }
+}
+
+fn get_target() -> String {
+    let output = Command::new("rustc")
+        .arg("-Vv")
+        .output()
+        .expect("rustc failed to run");
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    for line in stdout.lines() {
+        if line.starts_with("host: ") {
+            return String::from(&line[6..]);
+        }
+    }
+    panic!("Failed to find host: {}", stdout);
+}
+
+fn get_cfgs() -> Vec<Cfg> {
+    let output = Command::new("rustc")
+        .arg("--print=cfg")
+        .output()
+        .expect("rustc failed to run");
+    let stdout = String::from_utf8(output.stdout).unwrap();
+    stdout
+        .lines()
+        .map(|line| Cfg::from_str(line).unwrap())
+        .collect()
+}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs b/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs
new file mode 100644
index 0000000..c3ddb69bc
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/src/cfg.rs
@@ -0,0 +1,319 @@
+use crate::error::{ParseError, ParseErrorKind::*};
+use std::fmt;
+use std::iter;
+use std::str::{self, FromStr};
+
+/// A cfg expression.
+#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
+pub enum CfgExpr {
+    Not(Box<CfgExpr>),
+    All(Vec<CfgExpr>),
+    Any(Vec<CfgExpr>),
+    Value(Cfg),
+}
+
+/// A cfg value.
+#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
+pub enum Cfg {
+    /// A named cfg value, like `unix`.
+    Name(String),
+    /// A key/value cfg pair, like `target_os = "linux"`.
+    KeyPair(String, String),
+}
+
+#[derive(PartialEq)]
+enum Token<'a> {
+    LeftParen,
+    RightParen,
+    Ident(&'a str),
+    Comma,
+    Equals,
+    String(&'a str),
+}
+
+#[derive(Clone)]
+struct Tokenizer<'a> {
+    s: iter::Peekable<str::CharIndices<'a>>,
+    orig: &'a str,
+}
+
+struct Parser<'a> {
+    t: Tokenizer<'a>,
+}
+
+impl FromStr for Cfg {
+    type Err = ParseError;
+
+    fn from_str(s: &str) -> Result<Cfg, Self::Err> {
+        let mut p = Parser::new(s);
+        let e = p.cfg()?;
+        if let Some(rest) = p.rest() {
+            return Err(ParseError::new(
+                p.t.orig,
+                UnterminatedExpression(rest.to_string()),
+            ));
+        }
+        Ok(e)
+    }
+}
+
+impl fmt::Display for Cfg {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Cfg::Name(ref s) => s.fmt(f),
+            Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v),
+        }
+    }
+}
+
+impl CfgExpr {
+    /// Utility function to check if the key, "cfg(..)" matches the `target_cfg`
+    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {
+        if key.starts_with("cfg(") && key.ends_with(')') {
+            let cfg = &key[4..key.len() - 1];
+
+            CfgExpr::from_str(cfg)
+                .ok()
+                .map(|ce| ce.matches(target_cfg))
+                .unwrap_or(false)
+        } else {
+            false
+        }
+    }
+
+    pub fn matches(&self, cfg: &[Cfg]) -> bool {
+        match *self {
+            CfgExpr::Not(ref e) => !e.matches(cfg),
+            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
+            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
+            CfgExpr::Value(ref e) => cfg.contains(e),
+        }
+    }
+}
+
+impl FromStr for CfgExpr {
+    type Err = ParseError;
+
+    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {
+        let mut p = Parser::new(s);
+        let e = p.expr()?;
+        if let Some(rest) = p.rest() {
+            return Err(ParseError::new(
+                p.t.orig,
+                UnterminatedExpression(rest.to_string()),
+            ));
+        }
+        Ok(e)
+    }
+}
+
+impl fmt::Display for CfgExpr {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            CfgExpr::Not(ref e) => write!(f, "not({})", e),
+            CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
+            CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
+            CfgExpr::Value(ref e) => write!(f, "{}", e),
+        }
+    }
+}
+
+struct CommaSep<'a, T>(&'a [T]);
+
+impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        for (i, v) in self.0.iter().enumerate() {
+            if i > 0 {
+                write!(f, ", ")?;
+            }
+            write!(f, "{}", v)?;
+        }
+        Ok(())
+    }
+}
+
+impl<'a> Parser<'a> {
+    fn new(s: &'a str) -> Parser<'a> {
+        Parser {
+            t: Tokenizer {
+                s: s.char_indices().peekable(),
+                orig: s,
+            },
+        }
+    }
+
+    fn expr(&mut self) -> Result<CfgExpr, ParseError> {
+        match self.peek() {
+            Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => {
+                self.t.next();
+                let mut e = Vec::new();
+                self.eat(&Token::LeftParen)?;
+                while !self.r#try(&Token::RightParen) {
+                    e.push(self.expr()?);
+                    if !self.r#try(&Token::Comma) {
+                        self.eat(&Token::RightParen)?;
+                        break;
+                    }
+                }
+                if op == "all" {
+                    Ok(CfgExpr::All(e))
+                } else {
+                    Ok(CfgExpr::Any(e))
+                }
+            }
+            Some(Ok(Token::Ident("not"))) => {
+                self.t.next();
+                self.eat(&Token::LeftParen)?;
+                let e = self.expr()?;
+                self.eat(&Token::RightParen)?;
+                Ok(CfgExpr::Not(Box::new(e)))
+            }
+            Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
+            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
+            None => Err(ParseError::new(
+                self.t.orig,
+                IncompleteExpr("start of a cfg expression"),
+            )),
+        }
+    }
+
+    fn cfg(&mut self) -> Result<Cfg, ParseError> {
+        match self.t.next() {
+            Some(Ok(Token::Ident(name))) => {
+                let e = if self.r#try(&Token::Equals) {
+                    let val = match self.t.next() {
+                        Some(Ok(Token::String(s))) => s,
+                        Some(Ok(t)) => {
+                            return Err(ParseError::new(
+                                self.t.orig,
+                                UnexpectedToken {
+                                    expected: "a string",
+                                    found: t.classify(),
+                                },
+                            ))
+                        }
+                        Some(Err(e)) => return Err(e),
+                        None => {
+                            return Err(ParseError::new(self.t.orig, IncompleteExpr("a string")))
+                        }
+                    };
+                    Cfg::KeyPair(name.to_string(), val.to_string())
+                } else {
+                    Cfg::Name(name.to_string())
+                };
+                Ok(e)
+            }
+            Some(Ok(t)) => Err(ParseError::new(
+                self.t.orig,
+                UnexpectedToken {
+                    expected: "identifier",
+                    found: t.classify(),
+                },
+            )),
+            Some(Err(e)) => Err(e),
+            None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))),
+        }
+    }
+
+    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {
+        self.t.clone().next()
+    }
+
+    fn r#try(&mut self, token: &Token<'a>) -> bool {
+        match self.peek() {
+            Some(Ok(ref t)) if token == t => {}
+            _ => return false,
+        }
+        self.t.next();
+        true
+    }
+
+    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {
+        match self.t.next() {
+            Some(Ok(ref t)) if token == t => Ok(()),
+            Some(Ok(t)) => Err(ParseError::new(
+                self.t.orig,
+                UnexpectedToken {
+                    expected: token.classify(),
+                    found: t.classify(),
+                },
+            )),
+            Some(Err(e)) => Err(e),
+            None => Err(ParseError::new(
+                self.t.orig,
+                IncompleteExpr(token.classify()),
+            )),
+        }
+    }
+
+    /// Returns the rest of the input from the current location.
+    fn rest(&self) -> Option<&str> {
+        let mut s = self.t.s.clone();
+        loop {
+            match s.next() {
+                Some((_, ' ')) => {}
+                Some((start, _ch)) => return Some(&self.t.orig[start..]),
+                None => return None,
+            }
+        }
+    }
+}
+
+impl<'a> Iterator for Tokenizer<'a> {
+    type Item = Result<Token<'a>, ParseError>;
+
+    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {
+        loop {
+            match self.s.next() {
+                Some((_, ' ')) => {}
+                Some((_, '(')) => return Some(Ok(Token::LeftParen)),
+                Some((_, ')')) => return Some(Ok(Token::RightParen)),
+                Some((_, ',')) => return Some(Ok(Token::Comma)),
+                Some((_, '=')) => return Some(Ok(Token::Equals)),
+                Some((start, '"')) => {
+                    while let Some((end, ch)) = self.s.next() {
+                        if ch == '"' {
+                            return Some(Ok(Token::String(&self.orig[start + 1..end])));
+                        }
+                    }
+                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));
+                }
+                Some((start, ch)) if is_ident_start(ch) => {
+                    while let Some(&(end, ch)) = self.s.peek() {
+                        if !is_ident_rest(ch) {
+                            return Some(Ok(Token::Ident(&self.orig[start..end])));
+                        } else {
+                            self.s.next();
+                        }
+                    }
+                    return Some(Ok(Token::Ident(&self.orig[start..])));
+                }
+                Some((_, ch)) => {
+                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));
+                }
+                None => return None,
+            }
+        }
+    }
+}
+
+fn is_ident_start(ch: char) -> bool {
+    ch == '_' || ch.is_ascii_alphabetic()
+}
+
+fn is_ident_rest(ch: char) -> bool {
+    is_ident_start(ch) || ch.is_ascii_digit()
+}
+
+impl<'a> Token<'a> {
+    fn classify(&self) -> &'static str {
+        match *self {
+            Token::LeftParen => "`(`",
+            Token::RightParen => "`)`",
+            Token::Ident(..) => "an identifier",
+            Token::Comma => "`,`",
+            Token::Equals => "`=`",
+            Token::String(..) => "a string",
+        }
+    }
+}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/error.rs b/third_party/rust/cargo_platform/v0_1/crate/src/error.rs
new file mode 100644
index 0000000..bf4b35f
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/src/error.rs
@@ -0,0 +1,67 @@
+use std::fmt;
+
+#[derive(Debug)]
+pub struct ParseError {
+    kind: ParseErrorKind,
+    orig: String,
+}
+
+#[non_exhaustive]
+#[derive(Debug)]
+pub enum ParseErrorKind {
+    UnterminatedString,
+    UnexpectedChar(char),
+    UnexpectedToken {
+        expected: &'static str,
+        found: &'static str,
+    },
+    IncompleteExpr(&'static str),
+    UnterminatedExpression(String),
+    InvalidTarget(String),
+}
+
+impl fmt::Display for ParseError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "failed to parse `{}` as a cfg expression: {}",
+            self.orig, self.kind
+        )
+    }
+}
+
+impl fmt::Display for ParseErrorKind {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use ParseErrorKind::*;
+        match self {
+            UnterminatedString => write!(f, "unterminated string in cfg"),
+            UnexpectedChar(ch) => write!(
+                f,
+                "unexpected character `{}` in cfg, expected parens, a comma, \
+                 an identifier, or a string",
+                ch
+            ),
+            UnexpectedToken { expected, found } => {
+                write!(f, "expected {}, found {}", expected, found)
+            }
+            IncompleteExpr(expected) => {
+                write!(f, "expected {}, but cfg expression ended", expected)
+            }
+            UnterminatedExpression(s) => {
+                write!(f, "unexpected content `{}` found after cfg expression", s)
+            }
+            InvalidTarget(s) => write!(f, "invalid target specifier: {}", s),
+        }
+    }
+}
+
+impl std::error::Error for ParseError {}
+
+impl ParseError {
+    pub fn new(orig: &str, kind: ParseErrorKind) -> ParseError {
+        ParseError {
+            kind,
+            orig: orig.to_string(),
+        }
+    }
+}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs b/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs
new file mode 100644
index 0000000..0a3dcf1
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/src/lib.rs
@@ -0,0 +1,146 @@
+//! Platform definition used by Cargo.
+//!
+//! This defines a [`Platform`] type which is used in Cargo to specify a target platform.
+//! There are two kinds, a named target like `x86_64-apple-darwin`, and a "cfg expression"
+//! like `cfg(any(target_os = "macos", target_os = "ios"))`.
+//!
+//! See `examples/matches.rs` for an example of how to match against a `Platform`.
+//!
+//! [`Platform`]: enum.Platform.html
+
+use std::fmt;
+use std::str::FromStr;
+
+mod cfg;
+mod error;
+
+pub use cfg::{Cfg, CfgExpr};
+pub use error::{ParseError, ParseErrorKind};
+
+/// Platform definition.
+#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
+pub enum Platform {
+    /// A named platform, like `x86_64-apple-darwin`.
+    Name(String),
+    /// A cfg expression, like `cfg(windows)`.
+    Cfg(CfgExpr),
+}
+
+impl Platform {
+    /// Returns whether the Platform matches the given target and cfg.
+    ///
+    /// The named target and cfg values should be obtained from `rustc`.
+    pub fn matches(&self, name: &str, cfg: &[Cfg]) -> bool {
+        match *self {
+            Platform::Name(ref p) => p == name,
+            Platform::Cfg(ref p) => p.matches(cfg),
+        }
+    }
+
+    fn validate_named_platform(name: &str) -> Result<(), ParseError> {
+        if let Some(ch) = name
+            .chars()
+            .find(|&c| !(c.is_alphanumeric() || c == '_' || c == '-' || c == '.'))
+        {
+            if name.chars().any(|c| c == '(') {
+                return Err(ParseError::new(
+                    name,
+                    ParseErrorKind::InvalidTarget(
+                        "unexpected `(` character, cfg expressions must start with `cfg(`"
+                            .to_string(),
+                    ),
+                ));
+            }
+            return Err(ParseError::new(
+                name,
+                ParseErrorKind::InvalidTarget(format!(
+                    "unexpected character {} in target name",
+                    ch
+                )),
+            ));
+        }
+        Ok(())
+    }
+
+    pub fn check_cfg_attributes(&self, warnings: &mut Vec<String>) {
+        fn check_cfg_expr(expr: &CfgExpr, warnings: &mut Vec<String>) {
+            match *expr {
+                CfgExpr::Not(ref e) => check_cfg_expr(e, warnings),
+                CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {
+                    for e in e {
+                        check_cfg_expr(e, warnings);
+                    }
+                }
+                CfgExpr::Value(ref e) => match e {
+                    Cfg::Name(name) => match name.as_str() {
+                        "test" | "debug_assertions" | "proc_macro" =>
+                            warnings.push(format!(
+                                "Found `{}` in `target.'cfg(...)'.dependencies`. \
+                                 This value is not supported for selecting dependencies \
+                                 and will not work as expected. \
+                                 To learn more visit \
+                                 https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#platform-specific-dependencies",
+                                 name
+                            )),
+                        _ => (),
+                    },
+                    Cfg::KeyPair(name, _) => if name.as_str() == "feature" {
+                        warnings.push(String::from(
+                            "Found `feature = ...` in `target.'cfg(...)'.dependencies`. \
+                             This key is not supported for selecting dependencies \
+                             and will not work as expected. \
+                             Use the [features] section instead: \
+                             https://doc.rust-lang.org/cargo/reference/features.html"
+                        ))
+                    },
+                }
+            }
+        }
+
+        if let Platform::Cfg(cfg) = self {
+            check_cfg_expr(cfg, warnings);
+        }
+    }
+}
+
+impl serde::Serialize for Platform {
+    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
+    where
+        S: serde::Serializer,
+    {
+        self.to_string().serialize(s)
+    }
+}
+
+impl<'de> serde::Deserialize<'de> for Platform {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: serde::Deserializer<'de>,
+    {
+        let s = String::deserialize(deserializer)?;
+        FromStr::from_str(&s).map_err(serde::de::Error::custom)
+    }
+}
+
+impl FromStr for Platform {
+    type Err = ParseError;
+
+    fn from_str(s: &str) -> Result<Platform, ParseError> {
+        if s.starts_with("cfg(") && s.ends_with(')') {
+            let s = &s[4..s.len() - 1];
+            s.parse().map(Platform::Cfg)
+        } else {
+            Platform::validate_named_platform(s)?;
+            Ok(Platform::Name(s.to_string()))
+        }
+    }
+}
+
+impl fmt::Display for Platform {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Platform::Name(ref n) => n.fmt(f),
+            Platform::Cfg(ref e) => write!(f, "cfg({})", e),
+        }
+    }
+}
diff --git a/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs b/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs
new file mode 100644
index 0000000..dd99d9a
--- /dev/null
+++ b/third_party/rust/cargo_platform/v0_1/crate/tests/test_cfg.rs
@@ -0,0 +1,251 @@
+use cargo_platform::{Cfg, CfgExpr, Platform};
+use std::fmt;
+use std::str::FromStr;
+
+macro_rules! c {
+    ($a:ident) => {
+        Cfg::Name(stringify!($a).to_string())
+    };
+    ($a:ident = $e:expr) => {
+        Cfg::KeyPair(stringify!($a).to_string(), $e.to_string())
+    };
+}
+
+macro_rules! e {
+    (any($($t:tt),*)) => (CfgExpr::Any(vec![$(e!($t)),*]));
+    (all($($t:tt),*)) => (CfgExpr::All(vec![$(e!($t)),*]));
+    (not($($t:tt)*)) => (CfgExpr::Not(Box::new(e!($($t)*))));
+    (($($t:tt)*)) => (e!($($t)*));
+    ($($t:tt)*) => (CfgExpr::Value(c!($($t)*)));
+}
+
+fn good<T>(s: &str, expected: T)
+where
+    T: FromStr + PartialEq + fmt::Debug,
+    T::Err: fmt::Display,
+{
+    let c = match T::from_str(s) {
+        Ok(c) => c,
+        Err(e) => panic!("failed to parse `{}`: {}", s, e),
+    };
+    assert_eq!(c, expected);
+}
+
+fn bad<T>(s: &str, err: &str)
+where
+    T: FromStr + fmt::Display,
+    T::Err: fmt::Display,
+{
+    let e = match T::from_str(s) {
+        Ok(cfg) => panic!("expected `{}` to not parse but got {}", s, cfg),
+        Err(e) => e.to_string(),
+    };
+    assert!(
+        e.contains(err),
+        "when parsing `{}`,\n\"{}\" not contained \
+         inside: {}",
+        s,
+        err,
+        e
+    );
+}
+
+#[test]
+fn cfg_syntax() {
+    good("foo", c!(foo));
+    good("_bar", c!(_bar));
+    good(" foo", c!(foo));
+    good(" foo  ", c!(foo));
+    good(" foo  = \"bar\"", c!(foo = "bar"));
+    good("foo=\"\"", c!(foo = ""));
+    good(" foo=\"3\"      ", c!(foo = "3"));
+    good("foo = \"3 e\"", c!(foo = "3 e"));
+}
+
+#[test]
+fn cfg_syntax_bad() {
+    bad::<Cfg>("", "but cfg expression ended");
+    bad::<Cfg>(" ", "but cfg expression ended");
+    bad::<Cfg>("\t", "unexpected character");
+    bad::<Cfg>("7", "unexpected character");
+    bad::<Cfg>("=", "expected identifier");
+    bad::<Cfg>(",", "expected identifier");
+    bad::<Cfg>("(", "expected identifier");
+    bad::<Cfg>("foo (", "unexpected content `(` found after cfg expression");
+    bad::<Cfg>("bar =", "expected a string");
+    bad::<Cfg>("bar = \"", "unterminated string");
+    bad::<Cfg>(
+        "foo, bar",
+        "unexpected content `, bar` found after cfg expression",
+    );
+}
+
+#[test]
+fn cfg_expr() {
+    good("foo", e!(foo));
+    good("_bar", e!(_bar));
+    good(" foo", e!(foo));
+    good(" foo  ", e!(foo));
+    good(" foo  = \"bar\"", e!(foo = "bar"));
+    good("foo=\"\"", e!(foo = ""));
+    good(" foo=\"3\"      ", e!(foo = "3"));
+    good("foo = \"3 e\"", e!(foo = "3 e"));
+
+    good("all()", e!(all()));
+    good("all(a)", e!(all(a)));
+    good("all(a, b)", e!(all(a, b)));
+    good("all(a, )", e!(all(a)));
+    good("not(a = \"b\")", e!(not(a = "b")));
+    good("not(all(a))", e!(not(all(a))));
+}
+
+#[test]
+fn cfg_expr_bad() {
+    bad::<CfgExpr>(" ", "but cfg expression ended");
+    bad::<CfgExpr>(" all", "expected `(`");
+    bad::<CfgExpr>("all(a", "expected `)`");
+    bad::<CfgExpr>("not", "expected `(`");
+    bad::<CfgExpr>("not(a", "expected `)`");
+    bad::<CfgExpr>("a = ", "expected a string");
+    bad::<CfgExpr>("all(not())", "expected identifier");
+    bad::<CfgExpr>(
+        "foo(a)",
+        "unexpected content `(a)` found after cfg expression",
+    );
+}
+
+#[test]
+fn cfg_matches() {
+    assert!(e!(foo).matches(&[c!(bar), c!(foo), c!(baz)]));
+    assert!(e!(any(foo)).matches(&[c!(bar), c!(foo), c!(baz)]));
+    assert!(e!(any(foo, bar)).matches(&[c!(bar)]));
+    assert!(e!(any(foo, bar)).matches(&[c!(foo)]));
+    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
+    assert!(e!(all(foo, bar)).matches(&[c!(foo), c!(bar)]));
+    assert!(e!(not(foo)).matches(&[c!(bar)]));
+    assert!(e!(not(foo)).matches(&[]));
+    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(bar)]));
+    assert!(e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo), c!(bar)]));
+
+    assert!(!e!(foo).matches(&[]));
+    assert!(!e!(foo).matches(&[c!(bar)]));
+    assert!(!e!(foo).matches(&[c!(fo)]));
+    assert!(!e!(any(foo)).matches(&[]));
+    assert!(!e!(any(foo)).matches(&[c!(bar)]));
+    assert!(!e!(any(foo)).matches(&[c!(bar), c!(baz)]));
+    assert!(!e!(all(foo)).matches(&[c!(bar), c!(baz)]));
+    assert!(!e!(all(foo, bar)).matches(&[c!(bar)]));
+    assert!(!e!(all(foo, bar)).matches(&[c!(foo)]));
+    assert!(!e!(all(foo, bar)).matches(&[]));
+    assert!(!e!(not(bar)).matches(&[c!(bar)]));
+    assert!(!e!(not(bar)).matches(&[c!(baz), c!(bar)]));
+    assert!(!e!(any((not(foo)), (all(foo, bar)))).matches(&[c!(foo)]));
+}
+
+#[test]
+fn bad_target_name() {
+    bad::<Platform>(
+        "any(cfg(unix), cfg(windows))",
+        "failed to parse `any(cfg(unix), cfg(windows))` as a cfg expression: \
+         invalid target specifier: unexpected `(` character, \
+         cfg expressions must start with `cfg(`",
+    );
+    bad::<Platform>(
+        "!foo",
+        "failed to parse `!foo` as a cfg expression: \
+         invalid target specifier: unexpected character ! in target name",
+    );
+}
+
+#[test]
+fn round_trip_platform() {
+    fn rt(s: &str) {
+        let p = Platform::from_str(s).unwrap();
+        let s2 = p.to_string();
+        let p2 = Platform::from_str(&s2).unwrap();
+        assert_eq!(p, p2);
+    }
+    rt("x86_64-apple-darwin");
+    rt("foo");
+    rt("cfg(windows)");
+    rt("cfg(target_os = \"windows\")");
+    rt(
+        "cfg(any(all(any(target_os = \"android\", target_os = \"linux\"), \
+         any(target_arch = \"aarch64\", target_arch = \"arm\", target_arch = \"powerpc64\", \
+         target_arch = \"x86\", target_arch = \"x86_64\")), \
+         all(target_os = \"freebsd\", target_arch = \"x86_64\")))",
+    );
+}
+
+#[test]
+fn check_cfg_attributes() {
+    fn ok(s: &str) {
+        let p = Platform::Cfg(s.parse().unwrap());
+        let mut warnings = Vec::new();
+        p.check_cfg_attributes(&mut warnings);
+        assert!(
+            warnings.is_empty(),
+            "Expected no warnings but got: {:?}",
+            warnings,
+        );
+    }
+
+    fn warn(s: &str, names: &[&str]) {
+        let p = Platform::Cfg(s.parse().unwrap());
+        let mut warnings = Vec::new();
+        p.check_cfg_attributes(&mut warnings);
+        assert_eq!(
+            warnings.len(),
+            names.len(),
+            "Expecter warnings about {:?} but got {:?}",
+            names,
+            warnings,
+        );
+        for (name, warning) in names.iter().zip(warnings.iter()) {
+            assert!(
+                warning.contains(name),
+                "Expected warning about '{}' but got: {}",
+                name,
+                warning,
+            );
+        }
+    }
+
+    ok("unix");
+    ok("windows");
+    ok("any(not(unix), windows)");
+    ok("foo");
+
+    ok("target_arch = \"abc\"");
+    ok("target_feature = \"abc\"");
+    ok("target_os = \"abc\"");
+    ok("target_family = \"abc\"");
+    ok("target_env = \"abc\"");
+    ok("target_endian = \"abc\"");
+    ok("target_pointer_width = \"abc\"");
+    ok("target_vendor = \"abc\"");
+    ok("bar = \"def\"");
+
+    warn("test", &["test"]);
+    warn("debug_assertions", &["debug_assertions"]);
+    warn("proc_macro", &["proc_macro"]);
+    warn("feature = \"abc\"", &["feature"]);
+
+    warn("any(not(debug_assertions), windows)", &["debug_assertions"]);
+    warn(
+        "any(not(feature = \"def\"), target_arch = \"abc\")",
+        &["feature"],
+    );
+    warn(
+        "any(not(target_os = \"windows\"), proc_macro)",
+        &["proc_macro"],
+    );
+    warn(
+        "any(not(feature = \"windows\"), proc_macro)",
+        &["feature", "proc_macro"],
+    );
+    warn(
+        "all(not(debug_assertions), any(windows, proc_macro))",
+        &["debug_assertions", "proc_macro"],
+    );
+}
diff --git a/third_party/rust/semver/v1/BUILD.gn b/third_party/rust/semver/v1/BUILD.gn
index 1c1dec8..c2b1c20 100644
--- a/third_party/rust/semver/v1/BUILD.gn
+++ b/third_party/rust/semver/v1/BUILD.gn
@@ -23,7 +23,11 @@
   cargo_pkg_name = "semver"
   cargo_pkg_description =
       "Parser and evaluator for Cargo's flavor of Semantic Versioning"
-  features = [ "std" ]
+  deps = [ "//third_party/rust/serde/v1:lib" ]
+  features = [
+    "serde",
+    "std",
+  ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
 }
diff --git a/third_party/rust/serde_json/v1/BUILD.gn b/third_party/rust/serde_json/v1/BUILD.gn
index 5a005a1..89e19b2a 100644
--- a/third_party/rust/serde_json/v1/BUILD.gn
+++ b/third_party/rust/serde_json/v1/BUILD.gn
@@ -27,7 +27,10 @@
     "//third_party/rust/ryu/v1:lib",
     "//third_party/rust/serde/v1:lib",
   ]
-  features = [ "std" ]
+  features = [
+    "std",
+    "unbounded_depth",
+  ]
   build_root = "crate/build.rs"
   build_sources = [ "crate/build.rs" ]
 }
diff --git a/third_party/rust/third_party.toml b/third_party/rust/third_party.toml
index f15c4a8b..270dc03 100644
--- a/third_party/rust/third_party.toml
+++ b/third_party/rust/third_party.toml
@@ -77,4 +77,5 @@
 syn = {version = "1", features = ["full"]}
 
 # Used in Rust tool for BUILD.gn generation.
+cargo_metadata = "0.14"
 toml = "0.5"
diff --git a/tools/clang/scripts/package.py b/tools/clang/scripts/package.py
index 0dfb991..32a79a5 100755
--- a/tools/clang/scripts/package.py
+++ b/tools/clang/scripts/package.py
@@ -437,10 +437,14 @@
 
   # Check that all non-glob wanted files exist on disk.
   want = [w.replace('$V', RELEASE_VERSION) for w in want]
+  found_all_wanted_files = True
   for w in want:
     if '*' in w: continue
     if os.path.exists(os.path.join(LLVM_RELEASE_DIR, w)): continue
     print('wanted file "%s" but it did not exist' % w, file=sys.stderr)
+    found_all_wanted_files = False
+
+  if not found_all_wanted_files:
     return 1
 
   # Check that all reclient inputs are in the package.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 3a8b94d..f4da766 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -388,7 +388,7 @@
       'ios15-sdk-device': 'ios_device_release_static_bot_xctest',
       'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest',
       'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest',
-      'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest',
+      'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors',
       'lacros-amd64-generic-rel (goma cache silo)': 'chromeos_amd64-generic_lacros_rel',
       'lacros-amd64-generic-rel (reclient)': 'chromeos_amd64-generic-vm_lacros_rel_reclient',
       'lacros-amd64-generic-rel-fyi': 'chromeos_amd64-generic_lacros_rel_reclient',
@@ -673,6 +673,8 @@
     },
 
     'chromium.updater': {
+      'mac-updater-builder-arm64-dbg': 'updater_debug_bot_arm64',
+      'mac-updater-builder-arm64-rel': 'updater_release_bot_arm64',
       'mac-updater-builder-dbg': 'updater_debug_bot',
       'mac-updater-builder-rel': 'updater_release_bot',
       'win-updater-builder-dbg': 'updater_debug_bot_reclient',
@@ -819,7 +821,6 @@
       'mac12.0.arm64-blink-rel': 'release_bot_blink_arm64_minimal_symbols',
       'win10.20h2-blink-rel': 'release_bot_blink_x86_minimal_symbols',
       'win11-blink-rel': 'release_bot_blink_x64_minimal_symbols',
-      'win7-blink-rel': 'release_bot_blink_x86_minimal_symbols',
     },
 
     'tryserver.chrome': {
@@ -1169,7 +1170,7 @@
       'ios15-beta-simulator': 'ios_simulator_debug_static_bot_xctest',
       'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest',
       'ios16-beta-simulator': 'ios_simulator_debug_static_bot_xctest',
-      'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest',
+      'ios16-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors',
       'mac-arm64-on-arm64-rel': 'mac_arm64_release_trybot',
       'mac-builder-next-rel': 'mac_arm64_gpu_tests_release_bot_minimal_symbols_no_nacl',
       'mac-clang-tidy-rel': 'release_trybot',
@@ -2793,6 +2794,10 @@
         'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation', 'no_lld',
     ],
 
+    'ios_simulator_debug_static_bot_xctest_no_lld_treat_warnings_as_errors': [
+        'debug_static_bot', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation', 'no_lld', 'treat_warnings_as_errors'
+    ],
+
     'ios_simulator_debug_static_bot_xctest_reclient': [
         'debug_static_bot_reclient', 'ios', 'ios_simulator', 'ios_cpu_x64', 'xctest', 'ios_disable_xcode_project_generation',
     ],
@@ -3407,6 +3412,10 @@
       'updater_on_win_mac', 'debug_static_bot',
     ],
 
+    'updater_debug_bot_arm64': [
+      'arm64', 'updater_on_win_mac', 'debug_static_bot',
+    ],
+
     'updater_debug_bot_reclient': [
       'updater_on_win_mac', 'debug_static_bot_reclient',
     ],
@@ -3419,6 +3428,10 @@
       'updater_on_win_mac', 'release_bot',
     ],
 
+    'updater_release_bot_arm64': [
+      'arm64', 'updater_on_win_mac', 'release_bot',
+    ],
+
     'updater_release_bot_reclient': [
       'updater_on_win_mac', 'release_bot_reclient',
     ],
@@ -4348,6 +4361,10 @@
       'gn_args': 'use_thin_lto=true thin_lto_enable_optimizations=true',
     },
 
+   'treat_warnings_as_errors': {
+      'gn_args': 'treat_warnings_as_errors=false',
+    },
+
     'tsan': {
       'gn_args': 'is_tsan=true',
     },
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index 1c62ba2..37f808ae 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -906,7 +906,9 @@
       "target_cpu": "x64",
       "target_environment": "simulator",
       "target_os": "ios",
-      "use_goma": true
+      "treat_warnings_as_errors": false,
+      "use_goma": true,
+      "use_lld": false
     }
   },
   "lacros-amd64-generic-rel (goma cache silo)": {
diff --git a/tools/mb/mb_config_expectations/chromium.updater.json b/tools/mb/mb_config_expectations/chromium.updater.json
index ee66ff07..478b25d 100644
--- a/tools/mb/mb_config_expectations/chromium.updater.json
+++ b/tools/mb/mb_config_expectations/chromium.updater.json
@@ -1,4 +1,24 @@
 {
+  "mac-updater-builder-arm64-dbg": {
+    "gn_args": {
+      "enable_chromium_updater": true,
+      "is_component_build": false,
+      "is_debug": true,
+      "symbol_level": 1,
+      "target_cpu": "arm64",
+      "use_goma": true
+    }
+  },
+  "mac-updater-builder-arm64-rel": {
+    "gn_args": {
+      "dcheck_always_on": false,
+      "enable_chromium_updater": true,
+      "is_component_build": false,
+      "is_debug": false,
+      "target_cpu": "arm64",
+      "use_goma": true
+    }
+  },
   "mac-updater-builder-dbg": {
     "gn_args": {
       "enable_chromium_updater": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.blink.json b/tools/mb/mb_config_expectations/tryserver.blink.json
index f9c412f..c24b3c1c 100644
--- a/tools/mb/mb_config_expectations/tryserver.blink.json
+++ b/tools/mb/mb_config_expectations/tryserver.blink.json
@@ -128,17 +128,5 @@
       "target_cpu": "x64",
       "use_goma": true
     }
-  },
-  "win7-blink-rel": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "ffmpeg_branding": "Chrome",
-      "is_component_build": false,
-      "is_debug": false,
-      "proprietary_codecs": true,
-      "symbol_level": 1,
-      "target_cpu": "x86",
-      "use_goma": true
-    }
   }
 }
\ No newline at end of file
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
index 8bb4c9a1..a72e72b 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -461,7 +461,9 @@
       "target_cpu": "x64",
       "target_environment": "simulator",
       "target_os": "ios",
-      "use_goma": true
+      "treat_warnings_as_errors": false,
+      "use_goma": true,
+      "use_lld": false
     }
   },
   "mac-arm64-on-arm64-rel": {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index b7047a3..4a93fa5 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -21150,6 +21150,7 @@
   <int value="18" label="DELETE_PREV_SENT"/>
   <int value="19" label="NAV_NEXT_WORD"/>
   <int value="20" label="NAV_PREV_WORD"/>
+  <int value="21" label="SMART_DELETE_PHRASE"/>
 </enum>
 
 <enum name="CrosDictationToggleDictationMethod">
@@ -34541,7 +34542,7 @@
   <int value="1559" label="WMDESKSPRIVATE_UPDATEDESKTEMPLATE"/>
   <int value="1560" label="WMDESKSPRIVATE_GETSAVEDDESKTEMPLATES"/>
   <int value="1561" label="WMDESKSPRIVATE_DELETEDESKTEMPLATE"/>
-  <int value="1562" label="WMDESKSPRIVATE_LAUNCHDESKTEMPLATE"/>
+  <int value="1562" label="WMDESKSPRIVATE_LAUNCHDESK"/>
   <int value="1563" label="AUTOTESTPRIVATE_SETSHELFICONPIN"/>
   <int value="1564" label="SCRIPTING_GETREGISTEREDCONTENTSCRIPTS"/>
   <int value="1565" label="OS_TELEMETRY_GETVPDINFO"/>
@@ -34639,7 +34640,7 @@
   <int value="1656" label="ACCESSIBILITY_PRIVATE_INSTALLPUMPKINFORDICTATION"/>
   <int value="1657" label="BOOKMARKMANAGERPRIVATE_OPENINNEWTAB"/>
   <int value="1658" label="BOOKMARKMANAGERPRIVATE_OPENINNEWWINDOW"/>
-  <int value="1659" label="WMDESKSPRIVATE_REMOVEDESKANDCLOSEWINDOWS"/>
+  <int value="1659" label="WMDESKSPRIVATE_REMOVEDESK"/>
   <int value="1660" label="SHAREDSTORAGEPRIVATE_GET"/>
   <int value="1661" label="SHAREDSTORAGEPRIVATE_SET"/>
   <int value="1662" label="SHAREDSTORAGEPRIVATE_REMOVE"/>
@@ -58397,6 +58398,7 @@
   <int value="301536977" label="DetailedLanguageSettings:enabled"/>
   <int value="301630312" label="ForcedColors:disabled"/>
   <int value="301869874" label="NTPPhysicalWebPageSuggestions:disabled"/>
+  <int value="302725573" label="NewInstanceFromDraggedLink:enabled"/>
   <int value="302754902" label="MicMuteNotifications:disabled"/>
   <int value="303058039" label="AccountConsistency:disabled"/>
   <int value="303252119" label="AutofillExpandedPopupViews:disabled"/>
@@ -59406,6 +59408,7 @@
   <int value="966134219" label="CrostiniEnableDlc:disabled"/>
   <int value="966352185" label="PrivacyAdvisor:disabled"/>
   <int value="966415988" label="SyncPseudoUSSPasswords:enabled"/>
+  <int value="966626581" label="NewInstanceFromDraggedLink:disabled"/>
   <int value="966958557"
       label="CryptAuthV2DedupDeviceLastActivityTime:enabled"/>
   <int value="967706865" label="ForceEnablePasswordDomainCapabilities:enabled"/>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 257e04a7..2f142d5 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -134,19 +134,19 @@
                but there was in the last 2 minutes"/>
 </variants>
 
-<histogram name="PerformanceMonitor.AverageCPU4.Total{UsageScenario}"
+<histogram name="PerformanceMonitor.AverageCPU5.Total{UsageScenario}"
     units="1/100 %" expires_after="2022-11-30">
   <owner>fdoray@chromium.org</owner>
   <owner>pmonette@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
-    See definition of PerformanceClass.AverageCPU4.ProcessName. This is recorded
+    See definition of PerformanceClass.AverageCPU5.ProcessName. This is recorded
     for {UsageScenario} (see go/chrome_power_use_per_scenario).
   </summary>
   <token key="UsageScenario" variants="UsageScenario"/>
 </histogram>
 
-<histogram name="PerformanceMonitor.AverageCPU4.{ProcessName}" units="1/100 %"
+<histogram name="PerformanceMonitor.AverageCPU5.{ProcessName}" units="1/100 %"
     expires_after="2022-11-30">
   <owner>fdoray@chromium.org</owner>
   <owner>pmonette@chromium.org</owner>
@@ -166,6 +166,9 @@
     we know that short-lived processes are very common (see
     Renderer.ProcessLifetime). A future version of this metric will address this
     limitation.
+
+    ANOTHER NOTE: On Windows, this is not recorded on CPUs that do not support
+    constant rate TSC.
   </summary>
   <token key="ProcessName" variants="ProcessName"/>
 </histogram>
@@ -203,6 +206,19 @@
   <token key="ProcessName" variants="ProcessName"/>
 </histogram>
 
+<histogram name="PerformanceMonitor.HasPreciseCPUUsage" enum="Boolean"
+    expires_after="2022-09-30">
+  <owner>pmonette@chromium.org</owner>
+  <owner>catan-team@chromium.org</owner>
+  <summary>
+    Records whether or not the CPU supports constant rate TSC, which allows a
+    more precise calculation of the CPU usage of a process. Recorded during
+    startup when the ProcessMonitor is instantiated.
+
+    Only Recorded on Windows.
+  </summary>
+</histogram>
+
 <histogram name="PerformanceMonitor.IdleWakeups2.Total{UsageScenario}"
     units="WakeupsPerSecond" expires_after="2022-11-30">
   <owner>olivierli@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index acc0926..af9c16b 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -13057,7 +13057,8 @@
 </event>
 
 <event name="PageLoad" singular="True">
-  <owner>bmcquade@chromium.org</owner>
+  <owner>sullivan@chromium.org</owner>
+  <owner>chrome-metrics-team@google.com</owner>
   <summary>
     Core metrics associated with web page loads.
   </summary>
@@ -14701,7 +14702,7 @@
 </event>
 
 <event name="PageLoad.FromGoogleSearch" singular="True">
-  <owner>bmcquade@chromium.org</owner>
+  <owner>sullivan@chromium.org</owner>
   <owner>mushan@chromium.org</owner>
   <summary>
     Recorded for page loads that were navigated to via Google Search.
@@ -18487,7 +18488,6 @@
 </event>
 
 <event name="SubresourceFilter" singular="True">
-  <owner>bmcquade@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
     Recorded for page loads where subresource filtering policy was evaluated.
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index bd17757..c066a60 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,16 +5,16 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "80e7be4b409112767087a1c92fd17d95537e561b",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/8ad5ba6c8bd3d01daecd0df5c4cf33d70f5f7710/trace_processor_shell.exe"
+            "hash": "929c4fd292208274ef28469051c43c60ab7006da",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "58893933be305d3bfe0a72ebebcacde2ac3ca893",
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "mac": {
-            "hash": "f6d69cc6cddb6a1ddfa0cc0fae2b98b6adb38677",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/2e22f4e894ed9800027ff05dc0c7fe2217b033d6/trace_processor_shell"
+            "hash": "a91d33c8f0282a876c3481bbb24bc2463f7d4a97",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/31772328c517b725c81994e4b9b99aac18319e40/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "2ae07fc516b89c8ac44f70798f402c8f3e80bca4",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/8ad5ba6c8bd3d01daecd0df5c4cf33d70f5f7710/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/7479a87c2032ebc3504fb6bedbb688827a66bb4a/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
index 457757a..3029706 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.h
@@ -8,11 +8,12 @@
 #include <IOSurface/IOSurface.h>
 #include <QuartzCore/QuartzCore.h>
 
+#include <list>
 #include <memory>
-#include <vector>
 
 #include "base/mac/scoped_cftyperef.h"
 #include "base/mac/scoped_nsobject.h"
+#include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
 #include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
 #include "ui/gfx/geometry/rect.h"
@@ -84,8 +85,9 @@
 
   class RootLayer {
    public:
-    RootLayer();
+    RootLayer(CARendererLayerTree* tree);
 
+    RootLayer(RootLayer&&) = delete;
     RootLayer(const RootLayer&) = delete;
     RootLayer& operator=(const RootLayer&) = delete;
 
@@ -109,25 +111,28 @@
     // to nil, so that its destructor will not remove an active CALayer.
     void CommitToCA(CALayer* superlayer,
                     RootLayer* old_layer,
-                    const gfx::Size& pixel_size,
-                    float scale_factor);
+                    const gfx::Size& pixel_size);
 
     // Return true if the CALayer tree is just a video layer on a black or
     // transparent background, false otherwise.
     bool WantsFullcreenLowPowerBackdrop() const;
 
-    std::vector<ClipAndSortingLayer> clip_and_sorting_layers_;
+    // Tree that owns `this`.
+    const raw_ptr<CARendererLayerTree> tree_;
+
+    std::list<ClipAndSortingLayer> clip_and_sorting_layers_;
     base::scoped_nsobject<CALayer> ca_layer_;
   };
   class ClipAndSortingLayer {
    public:
-    ClipAndSortingLayer(bool is_clipped,
+    ClipAndSortingLayer(RootLayer* root_layer,
+                        bool is_clipped,
                         gfx::Rect clip_rect,
                         gfx::RRectF rounded_corner_bounds,
                         unsigned sorting_context_id,
                         bool is_singleton_sorting_context);
-    ClipAndSortingLayer(ClipAndSortingLayer&& layer);
 
+    ClipAndSortingLayer(ClipAndSortingLayer&& layer) = delete;
     ClipAndSortingLayer(const ClipAndSortingLayer&) = delete;
     ClipAndSortingLayer& operator=(const ClipAndSortingLayer&) = delete;
 
@@ -136,11 +141,13 @@
     ~ClipAndSortingLayer();
     void AddContentLayer(CARendererLayerTree* tree,
                          const CARendererLayerParams& params);
-    void CommitToCA(CALayer* superlayer,
-                    ClipAndSortingLayer* old_layer,
-                    float scale_factor);
+    void CommitToCA(ClipAndSortingLayer* old_layer);
+    CARendererLayerTree* tree() { return parent_layer_->tree_; }
 
-    std::vector<TransformLayer> transform_layers_;
+    // Parent layer that owns `this`, and child layers that `this` owns.
+    const raw_ptr<RootLayer> parent_layer_;
+    std::list<TransformLayer> transform_layers_;
+
     bool is_clipped_ = false;
     gfx::Rect clip_rect_;
     gfx::RRectF rounded_corner_bounds_;
@@ -151,9 +158,10 @@
   };
   class TransformLayer {
    public:
-    TransformLayer(const gfx::Transform& transform);
-    TransformLayer(TransformLayer&& layer);
+    TransformLayer(ClipAndSortingLayer* parent_layer,
+                   const gfx::Transform& transform);
 
+    TransformLayer(TransformLayer&& layer) = delete;
     TransformLayer(const TransformLayer&) = delete;
     TransformLayer& operator=(const TransformLayer&) = delete;
 
@@ -162,17 +170,19 @@
     ~TransformLayer();
     void AddContentLayer(CARendererLayerTree* tree,
                          const CARendererLayerParams& params);
-    void CommitToCA(CALayer* superlayer,
-                    TransformLayer* old_layer,
-                    float scale_factor);
+    void CommitToCA(TransformLayer* old_layer);
+    CARendererLayerTree* tree() { return parent_layer_->tree(); }
+
+    // Parent layer that owns `this`, and child layers that `this` owns.
+    const raw_ptr<ClipAndSortingLayer> parent_layer_;
+    std::list<ContentLayer> content_layers_;
 
     gfx::Transform transform_;
-    std::vector<ContentLayer> content_layers_;
     base::scoped_nsobject<CALayer> ca_layer_;
   };
   class ContentLayer {
    public:
-    ContentLayer(CARendererLayerTree* tree,
+    ContentLayer(TransformLayer* parent_layer,
                  base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
                  base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
                  const gfx::RectF& contents_rect,
@@ -183,17 +193,19 @@
                  float opacity,
                  unsigned filter,
                  gfx::ProtectedVideoType protected_video_type);
-    ContentLayer(ContentLayer&& layer);
 
+    ContentLayer(ContentLayer&& layer) = delete;
     ContentLayer(const ContentLayer&) = delete;
     ContentLayer& operator=(const ContentLayer&) = delete;
 
     // See the behavior of RootLayer for the effects of these functions on the
     // |ca_layer| member and |old_layer| argument.
     ~ContentLayer();
-    void CommitToCA(CALayer* parent,
-                    ContentLayer* old_layer,
-                    float scale_factor);
+    void CommitToCA(ContentLayer* old_layer);
+    CARendererLayerTree* tree() { return parent_layer_->tree(); }
+
+    // Parent layer that owns `this`.
+    const raw_ptr<TransformLayer> parent_layer_;
 
     // Ensure that the IOSurface be marked as in-use as soon as it is received.
     // When they are committed to the window server, that will also increment
@@ -234,7 +246,7 @@
     base::scoped_nsobject<CALayer> update_indicator_layer_;
   };
 
-  RootLayer root_layer_;
+  RootLayer root_layer_{this};
   float scale_factor_ = 1;
   bool has_committed_ = false;
   const bool allow_av_sample_buffer_display_layer_ = true;
diff --git a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
index 523f6bd8..21c075a 100644
--- a/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
+++ b/ui/accelerated_widget_mac/ca_renderer_layer_tree.mm
@@ -278,13 +278,13 @@
     if (old_tree->scale_factor_ == scale_factor)
       old_root_layer = &old_tree->root_layer_;
   }
+  scale_factor_ = scale_factor;
 
-  root_layer_.CommitToCA(superlayer, old_root_layer, pixel_size, scale_factor);
+  root_layer_.CommitToCA(superlayer, old_root_layer, pixel_size);
   // If there are any extra CALayers in |old_tree| that were not stolen by this
   // tree, they will be removed from the CALayer tree in this deallocation.
   old_tree.reset();
   has_committed_ = true;
-  scale_factor_ = scale_factor;
 }
 
 bool CARendererLayerTree::RootLayer::WantsFullcreenLowPowerBackdrop() const {
@@ -345,25 +345,26 @@
     return nullptr;
   }
   const ClipAndSortingLayer& clip_and_sorting =
-      root_layer_.clip_and_sorting_layers_[0];
+      root_layer_.clip_and_sorting_layers_.front();
   size_t transform_count = clip_and_sorting.transform_layers_.size();
   if (transform_count != 1) {
     DLOG(ERROR) << "Can only return contents IOSurface when there is 1 "
                 << "TransformLayer, there are " << transform_count << ".";
     return nullptr;
   }
-  const TransformLayer& transform = clip_and_sorting.transform_layers_[0];
+  const TransformLayer& transform = clip_and_sorting.transform_layers_.front();
   size_t content_count = transform.content_layers_.size();
   if (content_count != 1) {
     DLOG(ERROR) << "Can only return contents IOSurface when there is 1 "
                 << "ContentLayer, there are " << transform_count << ".";
     return nullptr;
   }
-  const ContentLayer& content = transform.content_layers_[0];
+  const ContentLayer& content = transform.content_layers_.front();
   return content.io_surface_.get();
 }
 
-CARendererLayerTree::RootLayer::RootLayer() {}
+CARendererLayerTree::RootLayer::RootLayer(CARendererLayerTree* tree)
+    : tree_(tree) {}
 
 // Note that for all destructors, the the CALayer will have been reset to nil if
 // another layer has taken it.
@@ -372,57 +373,35 @@
 }
 
 CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
+    RootLayer* parent_layer,
     bool is_clipped,
     gfx::Rect clip_rect,
     gfx::RRectF rounded_corner_bounds_arg,
     unsigned sorting_context_id,
     bool is_singleton_sorting_context)
-    : is_clipped_(is_clipped),
+    : parent_layer_(parent_layer),
+      is_clipped_(is_clipped),
       clip_rect_(clip_rect),
       rounded_corner_bounds_(rounded_corner_bounds_arg),
       sorting_context_id_(sorting_context_id),
       is_singleton_sorting_context_(is_singleton_sorting_context) {}
 
-CARendererLayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
-    ClipAndSortingLayer&& layer)
-    : transform_layers_(std::move(layer.transform_layers_)),
-      is_clipped_(layer.is_clipped_),
-      clip_rect_(layer.clip_rect_),
-      rounded_corner_bounds_(layer.rounded_corner_bounds_),
-      sorting_context_id_(layer.sorting_context_id_),
-      is_singleton_sorting_context_(layer.is_singleton_sorting_context_),
-      clipping_ca_layer_(layer.clipping_ca_layer_),
-      rounded_corner_ca_layer_(layer.rounded_corner_ca_layer_) {
-  // Ensure that the ca_layer be reset, so that when the destructor is called,
-  // the layer hierarchy is unaffected.
-  // TODO(ccameron): Add a move constructor for scoped_nsobject to do this
-  // automatically.
-  layer.clipping_ca_layer_.reset();
-  layer.rounded_corner_ca_layer_.reset();
-}
-
 CARendererLayerTree::ClipAndSortingLayer::~ClipAndSortingLayer() {
   [clipping_ca_layer_ removeFromSuperlayer];
   [rounded_corner_ca_layer_ removeFromSuperlayer];
 }
 
 CARendererLayerTree::TransformLayer::TransformLayer(
+    ClipAndSortingLayer* parent_layer,
     const gfx::Transform& transform)
-    : transform_(transform) {}
-
-CARendererLayerTree::TransformLayer::TransformLayer(TransformLayer&& layer)
-    : transform_(layer.transform_),
-      content_layers_(std::move(layer.content_layers_)),
-      ca_layer_(layer.ca_layer_) {
-  layer.ca_layer_.reset();
-}
+    : parent_layer_(parent_layer), transform_(transform) {}
 
 CARendererLayerTree::TransformLayer::~TransformLayer() {
   [ca_layer_ removeFromSuperlayer];
 }
 
 CARendererLayerTree::ContentLayer::ContentLayer(
-    CARendererLayerTree* tree,
+    TransformLayer* parent_layer,
     base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
     base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer,
     const gfx::RectF& contents_rect,
@@ -433,7 +412,8 @@
     float opacity,
     unsigned filter,
     gfx::ProtectedVideoType protected_video_type)
-    : io_surface_(io_surface),
+    : parent_layer_(parent_layer),
+      io_surface_(io_surface),
       cv_pixel_buffer_(cv_pixel_buffer),
       contents_rect_(contents_rect),
       rect_(rect),
@@ -453,7 +433,7 @@
   // transparent layers must use real colors to be eligible for low power
   // detachment in fullscreen.
   // https://crbug.com/633805
-  if (!io_surface && !tree->allow_solid_color_layers_ &&
+  if (!io_surface && !tree()->allow_solid_color_layers_ &&
       background_color_ != SK_ColorBLACK &&
       background_color_ != SK_ColorTRANSPARENT) {
     solid_color_contents_ = SolidColorContents::Get(background_color);
@@ -490,7 +470,7 @@
   } else if (io_surface) {
     // Only allow 4:2:0 frames which fill the layer's contents or protected
     // video to be promoted to AV layers.
-    if (tree->allow_av_sample_buffer_display_layer_) {
+    if (tree()->allow_av_sample_buffer_display_layer_) {
       if (contents_rect == gfx::RectF(0, 0, 1, 1)) {
         switch (IOSurfaceGetPixelFormat(io_surface)) {
           case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
@@ -544,28 +524,6 @@
   }
 }
 
-CARendererLayerTree::ContentLayer::ContentLayer(ContentLayer&& layer)
-    : io_surface_(layer.io_surface_),
-      cv_pixel_buffer_(layer.cv_pixel_buffer_),
-      solid_color_contents_(layer.solid_color_contents_),
-      contents_rect_(layer.contents_rect_),
-      rect_(layer.rect_),
-      background_color_(layer.background_color_),
-      io_surface_color_space_(layer.io_surface_color_space_),
-      ca_edge_aa_mask_(layer.ca_edge_aa_mask_),
-      opacity_(layer.opacity_),
-      ca_filter_(layer.ca_filter_),
-      type_(layer.type_),
-      video_type_can_downgrade_(layer.video_type_can_downgrade_),
-      protected_video_type_(layer.protected_video_type_),
-      ca_layer_(std::move(layer.ca_layer_)),
-      av_layer_(std::move(layer.av_layer_)),
-      update_indicator_layer_(std::move(layer.update_indicator_layer_)) {
-  DCHECK(!layer.ca_layer_);
-  DCHECK(!layer.av_layer_);
-  DCHECK(!update_indicator_layer_);
-}
-
 CARendererLayerTree::ContentLayer::~ContentLayer() {
   [ca_layer_ removeFromSuperlayer];
   [update_indicator_layer_ removeFromSuperlayer];
@@ -606,9 +564,9 @@
     }
   }
   if (needs_new_clip_and_sorting_layer) {
-    clip_and_sorting_layers_.push_back(ClipAndSortingLayer(
-        params.is_clipped, params.clip_rect, params.rounded_corner_bounds,
-        params.sorting_context_id, is_singleton_sorting_context));
+    clip_and_sorting_layers_.emplace_back(
+        this, params.is_clipped, params.clip_rect, params.rounded_corner_bounds,
+        params.sorting_context_id, is_singleton_sorting_context);
   }
   clip_and_sorting_layers_.back().AddContentLayer(tree, params);
   return true;
@@ -624,7 +582,7 @@
       needs_new_transform_layer = false;
   }
   if (needs_new_transform_layer)
-    transform_layers_.push_back(TransformLayer(params.transform));
+    transform_layers_.emplace_back(this, params.transform);
   transform_layers_.back().AddContentLayer(tree, params);
 }
 
@@ -649,16 +607,15 @@
     // cv_pixel_buffer = io_surface_image->cv_pixel_buffer();
     io_surface_color_space = params.image->color_space();
   }
-  content_layers_.push_back(ContentLayer(
-      tree, io_surface, cv_pixel_buffer, params.contents_rect, params.rect,
+  content_layers_.emplace_back(
+      this, io_surface, cv_pixel_buffer, params.contents_rect, params.rect,
       params.background_color, io_surface_color_space, params.edge_aa_mask,
-      params.opacity, params.filter, params.protected_video_type));
+      params.opacity, params.filter, params.protected_video_type);
 }
 
 void CARendererLayerTree::RootLayer::CommitToCA(CALayer* superlayer,
                                                 RootLayer* old_layer,
-                                                const gfx::Size& pixel_size,
-                                                float scale_factor) {
+                                                const gfx::Size& pixel_size) {
   if (old_layer) {
     DCHECK(old_layer->ca_layer_);
     std::swap(ca_layer_, old_layer->ca_layer_);
@@ -677,7 +634,7 @@
     // In fullscreen low power mode there exists a single video layer on a
     // solid black background.
     const gfx::RectF bg_rect(
-        ScaleSize(gfx::SizeF(pixel_size), 1 / scale_factor));
+        ScaleSize(gfx::SizeF(pixel_size), 1 / tree_->scale_factor_));
     if (gfx::RectF([ca_layer_ frame]) != bg_rect)
       [ca_layer_ setFrame:bg_rect.ToCGRect()];
     if (![ca_layer_ backgroundColor])
@@ -699,20 +656,28 @@
     DowngradeAVLayersToCALayers();
   }
 
-  for (size_t i = 0; i < clip_and_sorting_layers_.size(); ++i) {
-    ClipAndSortingLayer* old_clip_and_sorting_layer = nullptr;
-    if (old_layer && i < old_layer->clip_and_sorting_layers_.size()) {
-      old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers_[i];
+  auto children_it = clip_and_sorting_layers_.begin();
+  auto old_layer_children_it = old_layer
+                                   ? old_layer->clip_and_sorting_layers_.begin()
+                                   : std::list<ClipAndSortingLayer>::iterator();
+  while (children_it != clip_and_sorting_layers_.end()) {
+    auto& child_layer = *children_it;
+    children_it++;
+
+    ClipAndSortingLayer* old_child_layer = nullptr;
+    if (old_layer &&
+        old_layer_children_it != old_layer->clip_and_sorting_layers_.end()) {
+      old_child_layer = &(*old_layer_children_it);
+      old_layer_children_it++;
     }
-    clip_and_sorting_layers_[i].CommitToCA(
-        ca_layer_.get(), old_clip_and_sorting_layer, scale_factor);
+
+    child_layer.CommitToCA(old_child_layer);
   }
 }
 
 void CARendererLayerTree::ClipAndSortingLayer::CommitToCA(
-    CALayer* superlayer,
-    ClipAndSortingLayer* old_layer,
-    float scale_factor) {
+    ClipAndSortingLayer* old_layer) {
+  CALayer* superlayer = parent_layer_->ca_layer_.get();
   bool update_is_clipped = true;
   bool update_clip_rect = true;
   if (old_layer) {
@@ -736,7 +701,7 @@
         old_layer->rounded_corner_bounds_ != rounded_corner_bounds_) {
       gfx::RectF dip_rounded_corner_bounds =
           gfx::RectF(rounded_corner_bounds_.rect());
-      dip_rounded_corner_bounds.Scale(1 / scale_factor);
+      dip_rounded_corner_bounds.Scale(1 / tree()->scale_factor_);
 
       [rounded_corner_ca_layer_ setMasksToBounds:true];
 
@@ -753,7 +718,7 @@
 
       [rounded_corner_ca_layer_
           setCornerRadius:rounded_corner_bounds_.GetSimpleRadius() /
-                          scale_factor];
+                          tree()->scale_factor_];
     }
   } else {
     [rounded_corner_ca_layer_ setMasksToBounds:false];
@@ -772,7 +737,7 @@
   if (update_clip_rect) {
     if (is_clipped_) {
       gfx::RectF dip_clip_rect = gfx::RectF(clip_rect_);
-      dip_clip_rect.Scale(1 / scale_factor);
+      dip_clip_rect.Scale(1 / tree()->scale_factor_);
       [clipping_ca_layer_
           setPosition:CGPointMake(dip_clip_rect.x(), dip_clip_rect.y())];
       [clipping_ca_layer_ setBounds:CGRectMake(0, 0, dip_clip_rect.width(),
@@ -787,18 +752,28 @@
     }
   }
 
-  for (size_t i = 0; i < transform_layers_.size(); ++i) {
-    TransformLayer* old_transform_layer = nullptr;
-    if (old_layer && i < old_layer->transform_layers_.size())
-      old_transform_layer = &old_layer->transform_layers_[i];
-    transform_layers_[i].CommitToCA(rounded_corner_ca_layer_,
-                                    old_transform_layer, scale_factor);
+  auto children_it = transform_layers_.begin();
+  auto old_layer_children_it = old_layer
+                                   ? old_layer->transform_layers_.begin()
+                                   : std::list<TransformLayer>::iterator();
+  while (children_it != transform_layers_.end()) {
+    auto& child_layer = *children_it;
+    children_it++;
+
+    TransformLayer* old_child_layer = nullptr;
+    if (old_layer &&
+        old_layer_children_it != old_layer->transform_layers_.end()) {
+      old_child_layer = &(*old_layer_children_it);
+      old_layer_children_it++;
+    }
+
+    child_layer.CommitToCA(old_child_layer);
   }
 }
 
-void CARendererLayerTree::TransformLayer::CommitToCA(CALayer* superlayer,
-                                                     TransformLayer* old_layer,
-                                                     float scale_factor) {
+void CARendererLayerTree::TransformLayer::CommitToCA(
+    TransformLayer* old_layer) {
+  CALayer* superlayer = parent_layer_->rounded_corner_ca_layer_.get();
   bool update_transform = true;
   if (old_layer) {
     DCHECK(old_layer->ca_layer_);
@@ -813,8 +788,8 @@
   if (update_transform) {
     gfx::Transform pre_scale;
     gfx::Transform post_scale;
-    pre_scale.Scale(1 / scale_factor, 1 / scale_factor);
-    post_scale.Scale(scale_factor, scale_factor);
+    pre_scale.Scale(1 / tree()->scale_factor_, 1 / tree()->scale_factor_);
+    post_scale.Scale(tree()->scale_factor_, tree()->scale_factor_);
     gfx::Transform conjugated_transform = pre_scale * transform_ * post_scale;
 
     CATransform3D ca_transform =
@@ -822,18 +797,26 @@
     [ca_layer_ setTransform:ca_transform];
   }
 
-  for (size_t i = 0; i < content_layers_.size(); ++i) {
-    ContentLayer* old_content_layer = nullptr;
-    if (old_layer && i < old_layer->content_layers_.size())
-      old_content_layer = &old_layer->content_layers_[i];
-    content_layers_[i].CommitToCA(ca_layer_.get(), old_content_layer,
-                                  scale_factor);
+  auto children_it = content_layers_.begin();
+  auto old_layer_children_it = old_layer ? old_layer->content_layers_.begin()
+                                         : std::list<ContentLayer>::iterator();
+  while (children_it != content_layers_.end()) {
+    ContentLayer& child_layer = *children_it;
+    children_it++;
+
+    ContentLayer* old_child_layer = nullptr;
+    if (old_layer &&
+        old_layer_children_it != old_layer->content_layers_.end()) {
+      old_child_layer = &(*old_layer_children_it);
+      old_layer_children_it++;
+    }
+
+    child_layer.CommitToCA(old_child_layer);
   }
 }
 
-void CARendererLayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
-                                                   ContentLayer* old_layer,
-                                                   float scale_factor) {
+void CARendererLayerTree::ContentLayer::CommitToCA(ContentLayer* old_layer) {
+  CALayer* superlayer = parent_layer_->ca_layer_.get();
   bool update_contents = true;
   bool update_contents_rect = true;
   bool update_rect = true;
@@ -924,7 +907,7 @@
           [ca_layer_ setContents:nil];
         }
         if ([ca_layer_ respondsToSelector:(@selector(setContentsScale:))])
-          [ca_layer_ setContentsScale:scale_factor];
+          [ca_layer_ setContentsScale:tree()->scale_factor_];
       }
       break;
   }
@@ -935,7 +918,7 @@
   }
   if (update_rect) {
     gfx::RectF dip_rect = gfx::RectF(rect_);
-    dip_rect.Scale(1 / scale_factor);
+    dip_rect.Scale(1 / tree()->scale_factor_);
     [ca_layer_ setPosition:CGPointMake(dip_rect.x(), dip_rect.y())];
     [ca_layer_ setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())];
   }
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java
index a53e79ee1..c8cc0a4 100644
--- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java
+++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropBrowserDelegate.java
@@ -4,6 +4,7 @@
 
 package org.chromium.ui.dragdrop;
 
+import android.content.Intent;
 import android.view.DragAndDropPermissions;
 import android.view.DragEvent;
 
@@ -16,4 +17,7 @@
 
     /** Request DragAndDropPermissions. */
     DragAndDropPermissions getDragAndDropPermissions(DragEvent dropEvent);
+
+    /** Create an intent from a dragged text link. */
+    Intent createLinkIntent(String urlString);
 }
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java
index 762c981..0315ca0e 100644
--- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java
+++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegate.java
@@ -8,7 +8,7 @@
 import android.view.View;
 
 /**
- * Delegate to perform drag and drop operations, for example re-routing the call to {@link
+ * Delegate to facilitate Drag and Drop operations, for example re-routing the call to {@link
  * #startDragAndDrop(Bitmap, DropDataAndroid).}
  */
 public interface DragAndDropDelegate {
@@ -16,7 +16,8 @@
     boolean startDragAndDrop(View containerView, Bitmap shadowImage, DropDataAndroid dropData);
 
     /**
-     * Set the {@link DragAndDropBrowserDelegate} that will be used to get DragAndDropPermissions.
+     * Set the {@link DragAndDropBrowserDelegate} that will be used to facilitate browser related
+     * tasks required for Drag and Drop.
      * @param delegate The {@link DragAndDropBrowserDelegate} that will be used by this class.
      */
     default void setDragAndDropBrowserDelegate(DragAndDropBrowserDelegate delegate) {}
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
index a787c31..83972dab 100644
--- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
+++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
@@ -6,7 +6,9 @@
 
 import android.content.ClipData;
 import android.content.ClipData.Item;
+import android.content.ClipDescription;
 import android.content.Context;
+import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
@@ -72,7 +74,6 @@
     private int mShadowWidth;
     private int mShadowHeight;
     private boolean mIsDragStarted;
-    private boolean mDropInChrome;
 
     /** Whether the current drop has happened on top of the view this object tracks.  */
     private boolean mIsDropOnView;
@@ -202,6 +203,16 @@
                 }
                 return clipData;
             case DragTargetType.LINK:
+                if (mDragAndDropBrowserDelegate != null) {
+                    Intent intent =
+                            mDragAndDropBrowserDelegate.createLinkIntent(dropData.gurl.getSpec());
+                    if (intent != null) {
+                        return new ClipData(null,
+                                new String[] {ClipDescription.MIMETYPE_TEXT_PLAIN,
+                                        ClipDescription.MIMETYPE_TEXT_INTENT},
+                                new Item(getTextForLinkData(dropData), intent, null));
+                    }
+                }
                 return ClipData.newPlainText(null, getTextForLinkData(dropData));
             case DragTargetType.INVALID:
                 return null;
diff --git a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
index cfadb6d..d22c0de 100644
--- a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
+++ b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
@@ -7,11 +7,14 @@
 import static org.mockito.Mockito.doReturn;
 
 import android.content.ClipData;
+import android.content.ClipDescription;
 import android.content.Context;
+import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.drawable.VectorDrawable;
 import android.os.Build.VERSION_CODES;
 import android.util.Pair;
+import android.view.DragAndDropPermissions;
 import android.view.DragEvent;
 import android.view.View;
 import android.view.View.DragShadowBuilder;
@@ -339,6 +342,37 @@
                 clipData.getItemAt(1).getText());
     }
 
+    @Test
+    public void testClipData_TextLink() {
+        final DropDataAndroid dropData = DropDataAndroid.create(
+                "", JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL), null, null, null);
+        mDragAndDropDelegateImpl.setDragAndDropBrowserDelegate(new DragAndDropBrowserDelegate() {
+            @Override
+            public boolean getSupportDropInChrome() {
+                return false;
+            }
+
+            @Override
+            public DragAndDropPermissions getDragAndDropPermissions(DragEvent dropEvent) {
+                return null;
+            }
+
+            @Override
+            public Intent createLinkIntent(String urlString) {
+                return new Intent();
+            }
+        });
+        ClipData clipData = mDragAndDropDelegateImpl.buildClipData(dropData);
+        Assert.assertTrue("Link ClipData should include plaintext MIME type.",
+                clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN));
+        Assert.assertTrue("Link ClipData should include intent MIME type.",
+                clipData.getDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_INTENT));
+        Assert.assertEquals("Dragged link text should match.", JUnitTestGURLs.EXAMPLE_URL,
+                clipData.getItemAt(0).getText());
+        Assert.assertNotNull(
+                "ClipData intent should not be null.", clipData.getItemAt(0).getIntent());
+    }
+
     private void doTestResizeShadowImage(
             String testcase, int width, int height, int expectedWidth, int expectedHeight) {
         Pair<Integer, Integer> widthHeight =
diff --git a/ui/display/fake/fake_display_delegate.h b/ui/display/fake/fake_display_delegate.h
index f04def70..d1e6998b 100644
--- a/ui/display/fake/fake_display_delegate.h
+++ b/ui/display/fake/fake_display_delegate.h
@@ -31,14 +31,14 @@
 //   native_mode[#other_modes][^dpi][/options]
 //
 // native_mode: the native display mode, with format:
-//   HxW[%R]
-//     H: display height in pixels [int]
+//   WxH[%R]
 //     W: display width in pixels [int]
+//     H: display height in pixels [int]
 //     R: display refresh rate [float]
 //
 // other_modes: list of other of display modes, with format:
-//   #HxW[%R][:HxW[%R]]
-//     H,W,R: same meaning as in native_mode.
+//   #WxH[%R][:WxH[%R]]
+//     W,H,R: same meaning as in native_mode.
 //   Note: The first mode is delimited with '#' and any subsequent modes are
 //         delimited with ':'.
 //
diff --git a/ui/qt/qt_interface.h b/ui/qt/qt_interface.h
index 5115ed6..df4f1d546 100644
--- a/ui/qt/qt_interface.h
+++ b/ui/qt/qt_interface.h
@@ -59,9 +59,27 @@
   kFull,
 };
 
-enum class ColorRole {
+enum class ColorType {
   kWindowBg,
   kWindowFg,
+  kHighlightBg,
+  kHighlightFg,
+  kEntryBg,
+  kEntryFg,
+  kButtonBg,
+  kButtonFg,
+
+  kLight,
+  kMidlight,
+  kDark,
+  kMidground,
+  kShadow,
+};
+
+enum class ColorState {
+  kNormal,
+  kDisabled,
+  kInactive,
 };
 
 struct FontRenderParams {
@@ -105,7 +123,7 @@
   virtual FontDescription GetFontDescription() const = 0;
   virtual Image GetIconForContentType(const String& content_type,
                                       int size) const = 0;
-  virtual SkColor GetColor(ColorRole role) const = 0;
+  virtual SkColor GetColor(ColorType role, ColorState state) const = 0;
 };
 
 }  // namespace qt
diff --git a/ui/qt/qt_shim.cc b/ui/qt/qt_shim.cc
index abe4ba4..0cb5e4f6 100644
--- a/ui/qt/qt_shim.cc
+++ b/ui/qt/qt_shim.cc
@@ -146,6 +146,48 @@
   }
 }
 
+QPalette::ColorRole ColorTypeToColorRole(ColorType type) {
+  switch (type) {
+    case ColorType::kWindowBg:
+      return QPalette::Window;
+    case ColorType::kWindowFg:
+      return QPalette::WindowText;
+    case ColorType::kHighlightBg:
+      return QPalette::Highlight;
+    case ColorType::kHighlightFg:
+      return QPalette::HighlightedText;
+    case ColorType::kEntryBg:
+      return QPalette::Base;
+    case ColorType::kEntryFg:
+      return QPalette::Text;
+    case ColorType::kButtonBg:
+      return QPalette::Button;
+    case ColorType::kButtonFg:
+      return QPalette::ButtonText;
+    case ColorType::kLight:
+      return QPalette::Light;
+    case ColorType::kMidlight:
+      return QPalette::Midlight;
+    case ColorType::kMidground:
+      return QPalette::Mid;
+    case ColorType::kDark:
+      return QPalette::Dark;
+    case ColorType::kShadow:
+      return QPalette::Shadow;
+  }
+}
+
+QPalette::ColorGroup ColorStateToColorGroup(ColorState state) {
+  switch (state) {
+    case ColorState::kNormal:
+      return QPalette::Normal;
+    case ColorState::kDisabled:
+      return QPalette::Disabled;
+    case ColorState::kInactive:
+      return QPalette::Inactive;
+  }
+}
+
 }  // namespace
 
 QtShim::QtShim(QtInterface::Delegate* delegate, int* argc, char** argv)
@@ -202,14 +244,9 @@
   return {};
 }
 
-SkColor QtShim::GetColor(ColorRole role) const {
-  auto palette = app_.palette();
-  switch (role) {
-    case ColorRole::kWindowBg:
-      return BrushColor(palette.brush(QPalette::ColorRole::Window));
-    case ColorRole::kWindowFg:
-      return BrushColor(palette.brush(QPalette::ColorRole::WindowText));
-  }
+SkColor QtShim::GetColor(ColorType role, ColorState state) const {
+  return BrushColor(app_.palette().brush(ColorStateToColorGroup(state),
+                                         ColorTypeToColorRole(role)));
 }
 
 void QtShim::FontChanged(const QFont& font) {
diff --git a/ui/qt/qt_shim.h b/ui/qt/qt_shim.h
index ef680d22..8b707b81 100644
--- a/ui/qt/qt_shim.h
+++ b/ui/qt/qt_shim.h
@@ -28,7 +28,7 @@
   FontDescription GetFontDescription() const override;
   Image GetIconForContentType(const String& content_type,
                               int size) const override;
-  SkColor GetColor(ColorRole role) const override;
+  SkColor GetColor(ColorType role, ColorState state) const override;
 
  private slots:
   void FontChanged(const QFont& font);
diff --git a/ui/qt/qt_ui.cc b/ui/qt/qt_ui.cc
index f751d0a..35bc486 100644
--- a/ui/qt/qt_ui.cc
+++ b/ui/qt/qt_ui.cc
@@ -333,23 +333,48 @@
   // These color constants are required by native_chrome_color_mixer_linux.cc
   struct {
     ui::ColorId id;
-    SkColor color;
+    ColorType role;
+    ColorState state = ColorState::kNormal;
   } const kMaps[] = {
-      {ui::kColorNativeButtonBorder, gfx::kPlaceholderColor},
-      {ui::kColorNativeHeaderButtonBorderActive, gfx::kPlaceholderColor},
-      {ui::kColorNativeHeaderButtonBorderInactive, gfx::kPlaceholderColor},
-      {ui::kColorNativeHeaderSeparatorBorderActive, gfx::kPlaceholderColor},
-      {ui::kColorNativeHeaderSeparatorBorderInactive, gfx::kPlaceholderColor},
-      {ui::kColorNativeLabelForeground, shim_->GetColor(ColorRole::kWindowFg)},
-      {ui::kColorNativeTabForegroundInactiveFrameActive,
-       gfx::kPlaceholderColor},
-      {ui::kColorNativeTabForegroundInactiveFrameInactive,
-       gfx::kPlaceholderColor},
-      {ui::kColorNativeTextfieldBorderUnfocused, gfx::kPlaceholderColor},
-      {ui::kColorNativeToolbarBackground, gfx::kPlaceholderColor},
+      // Core colors
+      {ui::kColorAccent, ColorType::kHighlightBg},
+      {ui::kColorDisabledForeground, ColorType::kWindowFg,
+       ColorState::kDisabled},
+      {ui::kColorEndpointBackground, ColorType::kEntryBg},
+      {ui::kColorEndpointForeground, ColorType::kEntryFg},
+      {ui::kColorItemHighlight, ColorType::kHighlightBg},
+      {ui::kColorItemSelectionBackground, ColorType::kHighlightBg},
+      {ui::kColorMenuSelectionBackground, ColorType::kHighlightBg},
+      {ui::kColorMidground, ColorType::kMidground},
+      {ui::kColorPrimaryBackground, ColorType::kWindowBg},
+      {ui::kColorPrimaryForeground, ColorType::kWindowFg},
+      {ui::kColorSecondaryForeground, ColorType::kWindowFg,
+       ColorState::kDisabled},
+      {ui::kColorSubtleAccent, ColorType::kHighlightBg, ColorState::kInactive},
+      {ui::kColorSubtleEmphasisBackground, ColorType::kWindowBg},
+      {ui::kColorTextSelectionBackground, ColorType::kHighlightBg},
+      {ui::kColorTextSelectionForeground, ColorType::kHighlightFg},
+
+      // Platform-specific UI elements
+      {ui::kColorNativeButtonBorder,
+       // For flat-styled buttons, QT uses the text color as the button border.
+       ColorType::kWindowFg},
+      {ui::kColorNativeHeaderButtonBorderActive, ColorType::kWindowFg},
+      {ui::kColorNativeHeaderButtonBorderInactive, ColorType::kWindowFg,
+       ColorState::kInactive},
+      {ui::kColorNativeHeaderSeparatorBorderActive, ColorType::kWindowFg},
+      {ui::kColorNativeHeaderSeparatorBorderInactive, ColorType::kWindowFg,
+       ColorState::kInactive},
+      {ui::kColorNativeLabelForeground, ColorType::kWindowFg},
+      {ui::kColorNativeTabForegroundInactiveFrameActive, ColorType::kButtonFg},
+      {ui::kColorNativeTabForegroundInactiveFrameInactive, ColorType::kButtonFg,
+       ColorState::kInactive},
+      {ui::kColorNativeTextfieldBorderUnfocused, ColorType::kWindowFg,
+       ColorState::kInactive},
+      {ui::kColorNativeToolbarBackground, ColorType::kButtonBg},
   };
   for (const auto& map : kMaps)
-    mixer[map.id] = {map.color};
+    mixer[map.id] = {shim_->GetColor(map.role, map.state)};
 }
 
 std::unique_ptr<views::LinuxUI> CreateQtUi() {
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index b91e6b0b..8c979f96 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -14,7 +14,7 @@
   grd_prefix = "webui_generated"
   out_grd = "$target_gen_dir/${grd_prefix}_resources.grd"
 
-  deps = [
+  public_deps = [
     ":build_ts_grdp",
     "cr_components/color_change_listener:build_grdp",
     "css:build_grdp",
@@ -50,7 +50,7 @@
   }
 
   if (include_polymer) {
-    deps += [
+    public_deps += [
       "cr_components:build_grdp",
       "cr_components/app_management:build_grdp",
       "cr_components/customize_themes:build_grdp",
@@ -70,27 +70,27 @@
     ]
 
     if (use_nss_certs) {
-      deps += [ "cr_components/certificate_manager:build_grdp" ]
+      public_deps += [ "cr_components/certificate_manager:build_grdp" ]
       grdp_files +=
           [ "$target_gen_dir/cr_components/certificate_manager/resources.grdp" ]
     }
 
     # TODO(crbug.com/1184053): Fully remove once no longer used by CrOS.
     if (is_chromeos_ash) {
-      deps += [ "//third_party/polymer/v1_0:build_grdp" ]
+      public_deps += [ "//third_party/polymer/v1_0:build_grdp" ]
       grdp_files += [
         "$root_gen_dir/third_party/polymer/v1_0/polymer_1_0_resources.grdp",
       ]
     }
 
     if (!is_android) {
-      deps += [ "cr_components/history_clusters:build_grdp" ]
+      public_deps += [ "cr_components/history_clusters:build_grdp" ]
       grdp_files += [ "$root_gen_dir/ui/webui/resources/cr_components/history_clusters/resources.grdp" ]
     }
   }
 
   if (is_chromeos_ash) {
-    deps += [
+    public_deps += [
       ":build_cros_styles_grdp",
       "//ash/webui/common/resources:build_grdp",
       "//chromeos/ash/components/cros_elements:build_grdp",
@@ -107,7 +107,7 @@
   }
 
   if (!is_android && !is_ios) {
-    deps += [ "//third_party/lottie:build_grdp" ]
+    public_deps += [ "//third_party/lottie:build_grdp" ]
     grdp_files += [ "$root_gen_dir/third_party/lottie/resources.grdp" ]
   }
 }
@@ -116,7 +116,7 @@
   generate_grd("build_cros_styles_grdp") {
     grd_prefix = "webui"
     out_grd = "$target_gen_dir/cros_styles_resources.grdp"
-    deps = [ "//ui/chromeos/styles:cros_styles_css" ]
+    public_deps = [ "//ui/chromeos/styles:cros_styles_css" ]
     input_files_base_dir = rebase_path("$root_gen_dir/", root_build_dir)
     input_files = [ "ui/chromeos/styles/cros_styles.css" ]
     resource_path_rewrites =
@@ -157,7 +157,7 @@
 generate_grd("build_ts_grdp") {
   grd_prefix = "webui"
   out_grd = "$target_gen_dir/resources_ts.grdp"
-  deps = [ ":library" ]
+  public_deps = [ ":library" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
 }
 
diff --git a/ui/webui/resources/cr_components/BUILD.gn b/ui/webui/resources/cr_components/BUILD.gn
index e8fdf4b..04d8c49 100644
--- a/ui/webui/resources/cr_components/BUILD.gn
+++ b/ui/webui/resources/cr_components/BUILD.gn
@@ -22,7 +22,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "cr_components"
   out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp"
-  deps = [ ":preprocess" ]
+  public_deps = [ ":preprocess" ]
   if (is_chromeos_ash) {
     input_files_base_dir = rebase_path(".", "//")
     input_files = [
diff --git a/ui/webui/resources/cr_components/app_management/BUILD.gn b/ui/webui/resources/cr_components/app_management/BUILD.gn
index 69436d0..4855a2e 100644
--- a/ui/webui/resources/cr_components/app_management/BUILD.gn
+++ b/ui/webui/resources/cr_components/app_management/BUILD.gn
@@ -139,7 +139,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "cr_components_app_management"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/app_management"
 }
diff --git a/ui/webui/resources/cr_components/certificate_manager/BUILD.gn b/ui/webui/resources/cr_components/certificate_manager/BUILD.gn
index f1995f9..33d7ddec 100644
--- a/ui/webui/resources/cr_components/certificate_manager/BUILD.gn
+++ b/ui/webui/resources/cr_components/certificate_manager/BUILD.gn
@@ -63,7 +63,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "cr_components_certificate_manager"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/certificate_manager"
 }
diff --git a/ui/webui/resources/cr_components/color_change_listener/BUILD.gn b/ui/webui/resources/cr_components/color_change_listener/BUILD.gn
index a5d0fc36..97fa197 100644
--- a/ui/webui/resources/cr_components/color_change_listener/BUILD.gn
+++ b/ui/webui/resources/cr_components/color_change_listener/BUILD.gn
@@ -48,7 +48,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "cr_components_color_change_listener"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/color_change_listener"
 }
diff --git a/ui/webui/resources/cr_components/customize_themes/BUILD.gn b/ui/webui/resources/cr_components/customize_themes/BUILD.gn
index 4e8b44d..060c24d 100644
--- a/ui/webui/resources/cr_components/customize_themes/BUILD.gn
+++ b/ui/webui/resources/cr_components/customize_themes/BUILD.gn
@@ -78,7 +78,7 @@
     "colorize.svg",
     "brush.svg",
   ]
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/customize_themes"
 }
diff --git a/ui/webui/resources/cr_components/history_clusters/BUILD.gn b/ui/webui/resources/cr_components/history_clusters/BUILD.gn
index a0f8a489..cc3758de 100644
--- a/ui/webui/resources/cr_components/history_clusters/BUILD.gn
+++ b/ui/webui/resources/cr_components/history_clusters/BUILD.gn
@@ -44,7 +44,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "cr_components_history_clusters"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/history_clusters"
 }
diff --git a/ui/webui/resources/cr_components/most_visited/BUILD.gn b/ui/webui/resources/cr_components/most_visited/BUILD.gn
index b89c7b3..f2568f6 100644
--- a/ui/webui/resources/cr_components/most_visited/BUILD.gn
+++ b/ui/webui/resources/cr_components/most_visited/BUILD.gn
@@ -42,7 +42,7 @@
   grd_prefix = "cr_components_most_visited"
   out_grd = "$target_gen_dir/resources.grdp"
 
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "cr_components/most_visited"
 }
diff --git a/ui/webui/resources/cr_elements/BUILD.gn b/ui/webui/resources/cr_elements/BUILD.gn
index 25d422e..9a0313f6 100644
--- a/ui/webui/resources/cr_elements/BUILD.gn
+++ b/ui/webui/resources/cr_elements/BUILD.gn
@@ -26,7 +26,7 @@
   generate_grd("build_grdp") {
     grd_prefix = "cr_elements"
     out_grd = "$target_gen_dir/${grd_prefix}_resources.grdp"
-    deps = [ ":preprocess" ]
+    public_deps = [ ":preprocess" ]
     manifest_files = [ "$target_gen_dir/$preprocess_gen_manifest" ]
 
     if (is_chromeos_ash) {
diff --git a/ui/webui/resources/css/BUILD.gn b/ui/webui/resources/css/BUILD.gn
index 45073e77..3801cb7 100644
--- a/ui/webui/resources/css/BUILD.gn
+++ b/ui/webui/resources/css/BUILD.gn
@@ -13,7 +13,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "webui_css"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":preprocess_src" ]
+  public_deps = [ ":preprocess_src" ]
   manifest_files = [ "$target_gen_dir/$preprocess_src_manifest" ]
   resource_path_prefix = "css"
 }
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn
index c5b5f7a..40229e5 100644
--- a/ui/webui/resources/js/BUILD.gn
+++ b/ui/webui/resources/js/BUILD.gn
@@ -18,7 +18,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "webui_js"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":preprocess" ]
+  public_deps = [ ":preprocess" ]
   manifest_files = [
     "$target_gen_dir/$preprocess_gen_manifest",
     "$target_gen_dir/$preprocess_src_manifest",
diff --git a/ui/webui/resources/js/browser_command/BUILD.gn b/ui/webui/resources/js/browser_command/BUILD.gn
index cc43070..a8210ca 100644
--- a/ui/webui/resources/js/browser_command/BUILD.gn
+++ b/ui/webui/resources/js/browser_command/BUILD.gn
@@ -51,7 +51,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "webui_js_browser_command"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "js/browser_command"
 }
diff --git a/ui/webui/resources/js/cr/ui/BUILD.gn b/ui/webui/resources/js/cr/ui/BUILD.gn
index f3c4597..2743543 100644
--- a/ui/webui/resources/js/cr/ui/BUILD.gn
+++ b/ui/webui/resources/js/cr/ui/BUILD.gn
@@ -16,7 +16,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "webui_js_cr_ui"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":preprocess" ]
+  public_deps = [ ":preprocess" ]
   manifest_files = [
     "$target_gen_dir/$preprocess_gen_manifest",
     "$target_gen_dir/$preprocess_src_manifest",
diff --git a/ui/webui/resources/js/metrics_reporter/BUILD.gn b/ui/webui/resources/js/metrics_reporter/BUILD.gn
index d13ee52..497ec96 100644
--- a/ui/webui/resources/js/metrics_reporter/BUILD.gn
+++ b/ui/webui/resources/js/metrics_reporter/BUILD.gn
@@ -47,7 +47,7 @@
 generate_grd("build_grdp") {
   grd_prefix = "webui_js_metrics_reporter"
   out_grd = "$target_gen_dir/resources.grdp"
-  deps = [ ":build_ts" ]
+  public_deps = [ ":build_ts" ]
   manifest_files = [ "$target_gen_dir/tsconfig.manifest" ]
   resource_path_prefix = "js/metrics_reporter"
 }
diff --git a/ui/webui/resources/tools/generate_grd.gni b/ui/webui/resources/tools/generate_grd.gni
index 56464f3..7a99fc8 100644
--- a/ui/webui/resources/tools/generate_grd.gni
+++ b/ui/webui/resources/tools/generate_grd.gni
@@ -6,9 +6,11 @@
   action(target_name) {
     script = "//ui/webui/resources/tools/generate_grd.py"
 
-    if (defined(invoker.deps)) {
-      deps = invoker.deps
-    }
+    forward_variables_from(invoker,
+                           [
+                             "deps",
+                             "public_deps",
+                           ])
 
     inputs = []
     outputs = [ invoker.out_grd ]