diff --git a/DEPS b/DEPS
index 8da762d..ad65c2584 100644
--- a/DEPS
+++ b/DEPS
@@ -280,7 +280,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '2292a55e385c2c22ee4b0cf2e34fa4f5304b6241',
+  'skia_revision': 'c836692f20daf20fd717d2d45790e8ec42c53fd7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -288,7 +288,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': '669d7b756e7958e62420be211be1175a35340519',
+  'angle_revision': 'f86904290e1154bf72689987e78e735069d760e1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -307,7 +307,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
-  'fuchsia_version': 'version:8.20220627.1.1',
+  'fuchsia_version': 'version:8.20220627.3.1',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling google-toolbox-for-mac
   # and whatever else without interference from each other.
@@ -359,7 +359,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': '6c4b06be17e8a7ae237290a5589eacc6f89a47bf',
+  'devtools_frontend_revision': 'ac526b6b8bbe444262c5efa1ab62e39e68a2f0f5',
   # 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.
@@ -760,7 +760,7 @@
   },
 
   'src/ios/third_party/earl_grey2/src': {
-      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'e941da4d18403fb995fe0a5bd0d33074985099c7',
+      'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '11856053ebfc297d333ecae241e5dc20442ee8f4',
       'condition': 'checkout_ios',
   },
 
@@ -1156,7 +1156,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '418f021a0eddf7a207d8e5b68cccf0588c3a9724',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3c4d401cbdd24154d1fa6dc2d398fdace8daedf8',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1378,7 +1378,7 @@
     Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' +  Var('libfuzzer_revision'),
 
   'src/third_party/libaddressinput/src':
-    Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'a56be6f77ea76a9e77561ca306acede244631610',
+    Var('chromium_git') + '/external/libaddressinput.git' + '@' + 'df35d6c42da4fa2759e4cfb592afe33817993b89',
 
   'src/third_party/libaom/source/libaom':
     Var('aomedia_git') + '/aom.git' + '@' +  '42223eee8546d8f0d6a16c3f5f78a01298139976',
@@ -1720,10 +1720,10 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'e58ed2132aa47ac110a4cce1763abfa34f4fa34e',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '21e01f20feaa79eb125c34e7da02444715a19078',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e058d2287a163fe9de6bf3a048b77bf271e1ef94',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'd58f5263844df2e24604c7fff7a932c6baf6ade3',
+    Var('webrtc_git') + '/src.git' + '@' + '754f26f7b7d75aa18a596115f399c6e9026efa81',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1796,7 +1796,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@651b84b4189ae15e0d560044ed653dd0798f5bb3',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@23ecbd9464a1d52ce9e78fa0bf2b56cc0fa354fd',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc
index f862b96..974f031 100644
--- a/ash/constants/ash_features.cc
+++ b/ash/constants/ash_features.cc
@@ -1293,10 +1293,6 @@
 const base::Feature kScalableStatusArea{"ScalableStatusArea",
                                         base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enables the rounded corners for the internal display.
-const base::Feature kRoundedDisplay{"RoundedDisplay",
-                                    base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Controls whether to enable kSecondaryGoogleAccountUsage policy.
 const base::Feature kSecondaryGoogleAccountUsage{
     "SecondaryGoogleAccountUsage", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -2244,10 +2240,6 @@
   return base::FeatureList::IsEnabled(kScalableStatusArea);
 }
 
-bool IsRoundedDisplayEnabled() {
-  return base::FeatureList::IsEnabled(kRoundedDisplay);
-}
-
 bool IsSeparateNetworkIconsEnabled() {
   return base::FeatureList::IsEnabled(kSeparateNetworkIcons);
 }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h
index f10ed12..ed13f72 100644
--- a/ash/constants/ash_features.h
+++ b/ash/constants/ash_features.h
@@ -519,8 +519,6 @@
 extern const base::Feature kReverseScrollGestures;
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kScalableStatusArea;
 COMPONENT_EXPORT(ASH_CONSTANTS)
-extern const base::Feature kRoundedDisplay;
-COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kSecondaryGoogleAccountUsage;
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const base::Feature kSemanticColorsDebugOverride;
@@ -802,8 +800,6 @@
 bool IsSamlReauthenticationOnLockscreenEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSavedDesksEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsScalableStatusAreaEnabled();
-COMPONENT_EXPORT(ASH_CONSTANTS)
-bool IsRoundedDisplayEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS) bool IsSeparateNetworkIconsEnabled();
 COMPONENT_EXPORT(ASH_CONSTANTS)
 bool IsSettingsAppNotificationSettingsEnabled();
diff --git a/ash/constants/ash_switches.cc b/ash/constants/ash_switches.cc
index f387695..ba0810e3 100644
--- a/ash/constants/ash_switches.cc
+++ b/ash/constants/ash_switches.cc
@@ -225,6 +225,11 @@
 const char kAshHideNotificationsForFactory[] =
     "ash-hide-notifications-for-factory";
 
+// Hides educational nudges that can interfere with tast integration tests.
+// Somewhat similar to --no-first-run but affects system UI behavior, not
+// browser behavior.
+const char kAshNoNudges[] = "ash-no-nudges";
+
 // Power button position includes the power button's physical display side and
 // the percentage for power button center position to the display's
 // width/height in landscape_primary screen orientation. The value is a JSON
diff --git a/ash/constants/ash_switches.h b/ash/constants/ash_switches.h
index 30b6663..edd35d8c 100644
--- a/ash/constants/ash_switches.h
+++ b/ash/constants/ash_switches.h
@@ -76,6 +76,7 @@
 extern const char kAshForceStatusAreaCollapsible[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kAshHideNotificationsForFactory[];
+COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kAshNoNudges[];
 COMPONENT_EXPORT(ASH_CONSTANTS) extern const char kAshPowerButtonPosition[];
 COMPONENT_EXPORT(ASH_CONSTANTS)
 extern const char kAshSideVolumeButtonPosition[];
diff --git a/ash/public/cpp/wallpaper/wallpaper_controller_client.h b/ash/public/cpp/wallpaper/wallpaper_controller_client.h
index 95cde1d3..741e26d 100644
--- a/ash/public/cpp/wallpaper/wallpaper_controller_client.h
+++ b/ash/public/cpp/wallpaper/wallpaper_controller_client.h
@@ -34,9 +34,10 @@
       bool show_wallpaper,
       base::OnceCallback<void(bool success)> callback) = 0;
 
-  // Retrieves the current collection id from the Wallpaper Picker Chrome App
-  // for migration and returns it via |result_callback|. The string in
-  // |result_callback| will be empty if the fetch failed.
+  // Formerly retrieved the current collection id from the Wallpaper Picker
+  // Chrome App. Now always replies with empty string.
+  // TODO(b/193788853) delete this function now that it always replies with
+  // empty string.
   virtual void MigrateCollectionIdFromChromeApp(
       const AccountId& account_id,
       base::OnceCallback<void(const std::string&)> result_callback) = 0;
diff --git a/ash/shelf/launcher_nudge_controller.cc b/ash/shelf/launcher_nudge_controller.cc
index d6a1e765..2509c91 100644
--- a/ash/shelf/launcher_nudge_controller.cc
+++ b/ash/shelf/launcher_nudge_controller.cc
@@ -9,6 +9,7 @@
 #include "ash/app_list/app_list_controller_impl.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
+#include "ash/constants/ash_switches.h"
 #include "ash/public/cpp/session/session_types.h"
 #include "ash/root_window_controller.h"
 #include "ash/session/session_controller_impl.h"
@@ -17,6 +18,7 @@
 #include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_navigation_widget.h"
 #include "ash/shell.h"
+#include "base/command_line.h"
 #include "base/json/values_util.h"
 #include "base/time/time.h"
 #include "base/timer/wall_clock_timer.h"
@@ -148,6 +150,10 @@
   if (!prefs)
     return false;
 
+  // Do not show if the command line flag to hide nudges is set.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshNoNudges))
+    return false;
+
   if (GetFirstLoginTime(prefs).is_null()) {
     // Don't show the nudge to existing users. See
     // `OnActiveUserPrefServiceChanged()` for details.
diff --git a/ash/shelf/launcher_nudge_controller_unittest.cc b/ash/shelf/launcher_nudge_controller_unittest.cc
index 2e78eedaf..5a2e7d4 100644
--- a/ash/shelf/launcher_nudge_controller_unittest.cc
+++ b/ash/shelf/launcher_nudge_controller_unittest.cc
@@ -8,6 +8,7 @@
 #include "ash/app_list/test/app_list_test_helper.h"
 #include "ash/constants/ash_features.h"
 #include "ash/constants/ash_pref_names.h"
+#include "ash/constants/ash_switches.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shelf/home_button.h"
 #include "ash/shelf/scrollable_shelf_view.h"
@@ -17,6 +18,7 @@
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
+#include "base/command_line.h"
 #include "base/json/values_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
@@ -160,6 +162,14 @@
   EXPECT_EQ(0, GetNudgeShownCount());
 }
 
+TEST_F(LauncherNudgeControllerTest, NoNudgeWhenSkippedByCommandLineFlag) {
+  // Unit tests run with a scoped command line, so directly set the flag.
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kAshNoNudges);
+  SimulateUserLogin("user@gmail.com");
+  EXPECT_FALSE(nudge_controller_->IsRecheckTimerRunningForTesting());
+  EXPECT_EQ(0, GetNudgeShownCount());
+}
+
 TEST_F(LauncherNudgeControllerTest, DisableNudgeForExistingUser) {
   // Simulate a existing user logging in.
   SimulateUserLogin("user@gmail.com");
diff --git a/ash/style/dark_light_mode_nudge_controller.cc b/ash/style/dark_light_mode_nudge_controller.cc
index bdf2ff2..5a3544a 100644
--- a/ash/style/dark_light_mode_nudge_controller.cc
+++ b/ash/style/dark_light_mode_nudge_controller.cc
@@ -5,10 +5,12 @@
 #include "ash/style/dark_light_mode_nudge_controller.h"
 
 #include "ash/constants/ash_pref_names.h"
+#include "ash/constants/ash_switches.h"
 #include "ash/session/session_controller_impl.h"
 #include "ash/shell.h"
 #include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/style/dark_light_mode_nudge.h"
+#include "base/command_line.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -64,6 +66,10 @@
   if (hide_nudge_for_testing_)
     return false;
 
+  // Do not show if the command line flag to hide nudges is set.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshNoNudges))
+    return false;
+
   auto* session_controller = Shell::Get()->session_controller();
   if (!session_controller->IsActiveUserSessionStarted())
     return false;
diff --git a/ash/style/dark_light_mode_nudge_controller_unittests.cc b/ash/style/dark_light_mode_nudge_controller_unittests.cc
index 0365b97..4eca6f9 100644
--- a/ash/style/dark_light_mode_nudge_controller_unittests.cc
+++ b/ash/style/dark_light_mode_nudge_controller_unittests.cc
@@ -5,12 +5,14 @@
 #include "ash/style/dark_light_mode_nudge_controller.h"
 
 #include "ash/constants/ash_constants.h"
+#include "ash/constants/ash_switches.h"
 #include "ash/shell.h"
 #include "ash/style/dark_light_mode_controller_impl.h"
 #include "ash/system/dark_mode/dark_mode_feature_pod_controller.h"
 #include "ash/system/unified/unified_system_tray.h"
 #include "ash/system/unified/unified_system_tray_bubble.h"
 #include "ash/test/ash_test_base.h"
+#include "base/command_line.h"
 #include "base/test/scoped_feature_list.h"
 #include "chromeos/constants/chromeos_features.h"
 
@@ -51,6 +53,14 @@
             DarkLightModeNudgeController::GetRemainingShownCount());
 }
 
+TEST_F(DarkLightModeNudgeControllerTest, NoNudgeWhenSkippedByCommandLineFlag) {
+  // Unit tests run with a scoped command line, so directly set the flag.
+  base::CommandLine::ForCurrentProcess()->AppendSwitch(switches::kAshNoNudges);
+  SimulateUserLogin(account_id);
+  EXPECT_EQ(kDarkLightModeNudgeMaxShownCount,
+            DarkLightModeNudgeController::GetRemainingShownCount());
+}
+
 TEST_F(DarkLightModeNudgeControllerTest, NoNudgeInLockScreen) {
   SimulateUserLogin(account_id);
   EXPECT_EQ(kDarkLightModeNudgeMaxShownCount - 1,
diff --git a/ash/system/geolocation/geolocation_controller.cc b/ash/system/geolocation/geolocation_controller.cc
index 5ecad42..4319019 100644
--- a/ash/system/geolocation/geolocation_controller.cc
+++ b/ash/system/geolocation/geolocation_controller.cc
@@ -184,8 +184,8 @@
 
 base::Time GeolocationController::GetSunRiseSet(bool sunrise) const {
   if (!geoposition_) {
-    LOG(ERROR) << "Invalid geoposition. Using default time for "
-               << (sunrise ? "sunrise." : "sunset.");
+    VLOG(1) << "Invalid geoposition. Using default time for "
+            << (sunrise ? "sunrise." : "sunset.");
     return TimeOfDay(sunrise ? kDefaultSunriseTimeOffsetMinutes
                              : kDefaultSunsetTimeOffsetMinutes)
         .SetClock(clock_)
@@ -207,4 +207,4 @@
   return base::Time::FromDoubleT(sun_rise_set_ms / 1000.0);
 }
 
-}  // namespace ash
\ No newline at end of file
+}  // namespace ash
diff --git a/ash/system/time/calendar_utils.h b/ash/system/time/calendar_utils.h
index 0eaa88e..0111203 100644
--- a/ash/system/time/calendar_utils.h
+++ b/ash/system/time/calendar_utils.h
@@ -222,7 +222,7 @@
 // Gets the int index of this day in the week, starts from 1. This number is
 // different for different languages. If cannot find this local's day in a week,
 // returns its time exploded's `day_of_week`;
-int GetDayOfWeekInt(const base::Time date);
+ASH_EXPORT int GetDayOfWeekInt(const base::Time date);
 
 }  // namespace calendar_utils
 
diff --git a/ash/system/time/date_helper.cc b/ash/system/time/date_helper.cc
index b7a36b3..c096909 100644
--- a/ash/system/time/date_helper.cc
+++ b/ash/system/time/date_helper.cc
@@ -22,6 +22,12 @@
 // Milliseconds per minute.
 constexpr int kMillisecondsPerMinute = 60000;
 
+// Default week title for a few special languages that cannot find the start of
+// a week. So far the known languages that cannot return their day of week are:
+// 'bn', 'fa', 'mr', 'pa-PK'.
+const std::vector<std::u16string> kDefaultWeekTitle = {u"S", u"M", u"T", u"W",
+                                                       u"T", u"F", u"S"};
+
 UDate TimeToUDate(const base::Time& time) {
   return static_cast<UDate>(time.ToDoubleT() *
                             base::Time::kMillisecondsPerSecond);
@@ -178,6 +184,13 @@
       CreateDateIntervalFormatter("Hm");
 }
 
+void DateHelper::ResetForTesting() {
+  ResetFormatters();
+  CalculateLocalWeekTitles();
+  gregorian_calendar_->setTimeZone(
+      system::TimezoneSettings::GetInstance()->GetTimezone());
+}
+
 void DateHelper::CalculateLocalWeekTitles() {
   week_titles_.clear();
 
diff --git a/ash/system/time/date_helper.h b/ash/system/time/date_helper.h
index a9400c00..01680cf1 100644
--- a/ash/system/time/date_helper.h
+++ b/ash/system/time/date_helper.h
@@ -21,14 +21,6 @@
 
 namespace ash {
 
-namespace {
-// Default week title for a few special languages that cannot find the start of
-// a week. So far the known languages that cannot return their day of week are:
-// 'bn', 'fa', 'mr', 'pa-PK'.
-std::vector<std::u16string> kDefaultWeekTitle = {u"S", u"M", u"T", u"W",
-                                                 u"T", u"F", u"S"};
-}  // namespace
-
 // A singleton class used to create and cache `GregorianCalendar`,
 // `icu::SimpleDateFormat` and `icu::DateIntervalFormat` objects, so that they
 // don't have to be recreated each time when querying the time difference or
@@ -66,7 +58,7 @@
 
   // Get the time difference to UTC time based on the time passed in and the
   // system timezone. Daylight saving is considered.
-  base::TimeDelta GetTimeDifference(base::Time date) const;
+  ASH_EXPORT base::TimeDelta GetTimeDifference(base::Time date) const;
 
   // Gets the local midnight in UTC time of the `date`.
   // e.g. If the `date` is Apr 1st 1:00 (which is Mar 31st 18:00 PST), the
@@ -126,6 +118,9 @@
 
   std::vector<std::u16string> week_titles() { return week_titles_; }
 
+  // Reset after a locale change in the test.
+  ASH_EXPORT void ResetForTesting();
+
  private:
   friend base::DefaultSingletonTraits<DateHelper>;
   friend class DateHelperUnittest;
diff --git a/ash/webui/os_feedback_ui/os_feedback_ui.cc b/ash/webui/os_feedback_ui/os_feedback_ui.cc
index c836fac..6e26eba1 100644
--- a/ash/webui/os_feedback_ui/os_feedback_ui.cc
+++ b/ash/webui/os_feedback_ui/os_feedback_ui.cc
@@ -79,6 +79,7 @@
       {"anonymousUser", IDS_FEEDBACK_TOOL_ANONYMOUS_EMAIL_OPTION},
       {"thankYouNoteOffline", IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_OFFLINE},
       {"thankYouNoteOnline", IDS_FEEDBACK_TOOL_THANK_YOU_NOTE_ONLINE},
+      {"helpResourcesLabel", IDS_FEEDBACK_TOOL_HELP_RESOURCES_LABEL},
   };
 
   source->AddLocalizedStrings(kLocalizedStrings);
diff --git a/ash/webui/os_feedback_ui/resources/confirmation_page.html b/ash/webui/os_feedback_ui/resources/confirmation_page.html
index 069bd15..c865582 100644
--- a/ash/webui/os_feedback_ui/resources/confirmation_page.html
+++ b/ash/webui/os_feedback_ui/resources/confirmation_page.html
@@ -18,6 +18,22 @@
     font-weight: 400;
     line-height: 18px;
   }
+
+  .label {
+    color: var(--cros-text-color-primary);
+    font-family: 'Roboto';
+    font-size: 14px;
+    font-weight: var(--feedback-medium-font-weight);
+    line-height: 20px;
+  }
+
+  .sub-label {
+    color: var(--cros-text-color-secondary);
+    font-family: 'Roboto';
+    font-size: 13px;
+    font-weight: var(--feedback-regular-font-weight);
+    line-height: 20px;
+  }
 </style>
 <!--TODO(xiangdongkong): use localized strings -->
 <div id="container">
@@ -27,23 +43,31 @@
   <div id="content">
     <div id="message">[[getMessage_(sendReportStatus)]]</div>
     <div id="helpResources">
-      <p id="helpResourcesLabel">Here are some other helpful resources:</p>
+      <p id="helpResourcesLabel">[[i18n('helpResourcesLabel')]]</p>
       <cr-link-row id="explore" start-icon="help-resources:explore"
-          label="[[i18n('exploreAppLabel')]]" external
-          sub-label="[[i18n('exploreAppDescription')]]"
+          external using-slotted-label
           on-click="handleLinkClicked_">
+          <span slot="label" class="label">[[i18n('exploreAppLabel')]]</span>
+          <span slot="sub-label"
+              class="sub-label">[[i18n('exploreAppDescription')]]
+          </span>
       </cr-link-row>
       <cr-link-row id="diagnostics" start-icon="help-resources:diagnostics"
-          label="[[i18n('diagnosticsAppLabel')]]" external
-          sub-label="[[i18n('diagnosticsAppDescription')]]"
+          external using-slotted-label
           on-click="handleLinkClicked_">
+          <span slot="label" class="label">[[i18n('diagnosticsAppLabel')]]</span>
+          <span slot="sub-label"
+              class="sub-label">[[i18n('diagnosticsAppDescription')]]
+          </span>
       </cr-link-row>
       <cr-link-row id="chromebookCommunity"
           start-icon="help-resources2:chromebook-community"
-          label="[[i18n('askCommunityLabel')]]"
-          sub-label="[[i18n('askCommunityDescription')]]"
-          hidden="[[isOffline_(sendReportStatus)]]" external
+          hidden="[[isOffline_(sendReportStatus)]]" external using-slotted-label
           on-click="handleLinkClicked_">
+          <span slot="label" class="label">[[i18n('askCommunityLabel')]]</span>
+          <span slot="sub-label"
+              class="sub-label">[[i18n('askCommunityDescription')]]
+          </span>
       </cr-link-row>
     </div>
   </div>
diff --git a/ash/webui/os_feedback_ui/resources/help_content.html b/ash/webui/os_feedback_ui/resources/help_content.html
index 62ee9b40..038a101e 100644
--- a/ash/webui/os_feedback_ui/resources/help_content.html
+++ b/ash/webui/os_feedback_ui/resources/help_content.html
@@ -1,7 +1,9 @@
 <style>
-  a[href] {
-    color: var(--cros-text-color-primary);
-    text-decoration: none;
+  .help-content-label {
+    color: var(--cros-text-color-secondary);
+    font-size: 15px;
+    font-weight: 500;
+    margin: 24px 0 0;
   }
 
   .help-item {
@@ -9,16 +11,18 @@
     margin:  12px 0 0;
   }
 
+  .help-item a {
+    color: var(--cros-text-color-primary);
+    font-size: 13px;
+    text-decoration: none;
+  }
+
   iron-icon {
     padding-inline-end: 12px;
   }
-
-  #helpContentLabel {
-    margin: 24px 0 0;
-  }
 </style>
 <div id="helpContentContainer">
-  <h2 id="helpContentLabel">[[getLabel_(searchResult)]]</h2>
+  <h2 class="help-content-label">[[getLabel_(searchResult)]]</h2>
   <dom-repeat items="[[searchResult.contentList]]">
     <template>
       <div class="help-item">
diff --git a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
index 664ddfa5..9c849242 100644
--- a/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
+++ b/ash/webui/os_feedback_ui/resources/os_feedback_shared_css.html
@@ -2,6 +2,7 @@
   <style include="cr-shared-style">
     :host {
       --feedback-google-sans-font-family: "Google Sans", Roboto, sans-serif;
+      --feedback-regular-font-weight: 400;
       --feedback-medium-font-weight: 500;
     }
 
diff --git a/ash/wm/float/float_controller.cc b/ash/wm/float/float_controller.cc
index 63a5ce1..33be196 100644
--- a/ash/wm/float/float_controller.cc
+++ b/ash/wm/float/float_controller.cc
@@ -8,13 +8,16 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
 #include "ash/wm/desks/desks_util.h"
+#include "ash/wm/splitview/split_view_constants.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/tablet_mode/tablet_mode_window_state.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/work_area_insets.h"
 #include "base/check_op.h"
+#include "chromeos/ui/base/display_util.h"
 #include "chromeos/ui/base/window_properties.h"
 #include "ui/aura/window_delegate.h"
+#include "ui/display/screen.h"
 
 namespace ash {
 
@@ -33,14 +36,29 @@
   return Shell::Get()->tablet_mode_controller()->InTabletMode();
 }
 
-gfx::Size GetPreferredFloatWindowTabletSize(const gfx::Rect& work_area) {
+gfx::Size GetPreferredFloatWindowTabletSize(const gfx::Rect& work_area,
+                                            bool landscape) {
+  // We use the landscape bounds to determine the preferred width and height,
+  // even in portrait mode.
+  const int landscape_width =
+      landscape ? work_area.width() : work_area.height();
+  const int landscape_height =
+      landscape ? work_area.height() : work_area.width();
   const int preferred_width =
-      static_cast<int>(work_area.width() * kFloatWindowTabletWidthRatio);
-  const int preferred_height =
-      work_area.height() * kFloatWindowTabletHeightRatio;
+      static_cast<int>(landscape_width * kFloatWindowTabletWidthRatio);
+  const int preferred_height = landscape_height * kFloatWindowTabletHeightRatio;
   return gfx::Size(preferred_width, preferred_height);
 }
 
+// Returns whether the display nearest `window` is in landscape orientation.
+bool IsLandscapeOrientationForWindow(aura::Window* window) {
+  display::Display display =
+      display::Screen::GetScreen()->GetDisplayNearestWindow(window);
+  const chromeos::OrientationType orientation = chromeos::RotationToOrientation(
+      chromeos::GetDisplayNaturalOrientation(display), display.rotation());
+  return chromeos::IsLandscapeOrientation(orientation);
+}
+
 }  // namespace
 
 FloatController::FloatController() = default;
@@ -53,7 +71,9 @@
   DCHECK(CanFloatWindowInTablet(window));
   const gfx::Rect work_area = WorkAreaInsets::ForWindow(window->GetRootWindow())
                                   ->user_work_area_bounds();
-  const gfx::Size preferred_size = GetPreferredFloatWindowTabletSize(work_area);
+  const bool landscape = IsLandscapeOrientationForWindow(window);
+  const gfx::Size preferred_size =
+      GetPreferredFloatWindowTabletSize(work_area, landscape);
   const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
 
   const int width = std::max(preferred_size.width(), minimum_size.width());
@@ -77,11 +97,20 @@
 
   const gfx::Rect work_area = WorkAreaInsets::ForWindow(window->GetRootWindow())
                                   ->user_work_area_bounds();
+  const bool landscape = IsLandscapeOrientationForWindow(window);
   const int preferred_height =
-      GetPreferredFloatWindowTabletSize(work_area).height();
+      GetPreferredFloatWindowTabletSize(work_area, landscape).height();
   const gfx::Size minimum_size = window->delegate()->GetMinimumSize();
-  if (minimum_size.width() > work_area.width() / 2 ||
-      minimum_size.height() > preferred_height) {
+  if (minimum_size.height() > preferred_height)
+    return false;
+
+  const int landscape_width =
+      landscape ? work_area.width() : work_area.height();
+  // The maximize size for a floated window is half the landscape width minus
+  // some space for the split view divider and padding.
+  if (minimum_size.width() >
+      ((landscape_width - kSplitviewDividerShortSideLength) / 2 -
+       kFloatWindowPaddingDp * 2)) {
     return false;
   }
   return true;
@@ -123,8 +152,11 @@
   DCHECK(float_window_);
   if ((display::DisplayObserver::DISPLAY_METRIC_WORK_AREA & metrics) == 0)
     return;
+
   if (!CanFloatWindowInTablet(float_window_))
     ResetFloatedWindow();
+  else
+    MaybeUpdateWindowUIAndBoundsForTablet(float_window_);
 }
 
 void FloatController::Float(aura::Window* window) {
diff --git a/ash/wm/float/float_controller_unittest.cc b/ash/wm/float/float_controller_unittest.cc
index d3204094..10ee0f0e 100644
--- a/ash/wm/float/float_controller_unittest.cc
+++ b/ash/wm/float/float_controller_unittest.cc
@@ -6,6 +6,8 @@
 
 #include "ash/accelerators/accelerator_controller_impl.h"
 #include "ash/constants/ash_features.h"
+#include "ash/display/screen_orientation_controller_test_api.h"
+#include "ash/public/cpp/shelf_config.h"
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
@@ -13,6 +15,7 @@
 #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller.h"
 #include "chromeos/ui/wm/features.h"
 #include "ui/aura/test/test_window_delegate.h"
+#include "ui/display/test/display_manager_test_api.h"
 #include "ui/wm/core/window_util.h"
 
 namespace ash {
@@ -64,9 +67,11 @@
   EXPECT_FALSE(controller->IsFloated(window_2.get()));
 }
 
+using TabletWindowFloatTest = WindowFloatTest;
+
 // Tests that a window can be floated in tablet mode, unless its minimum width
 // is greater than half the work area.
-TEST_F(WindowFloatTest, TabletPositioningLandscape) {
+TEST_F(TabletWindowFloatTest, TabletPositioningLandscape) {
   UpdateDisplay("800x600");
 
   aura::test::TestWindowDelegate window_delegate;
@@ -91,7 +96,7 @@
 
 // Tests that a window that cannot be floated in tablet mode unfloats after
 // entering tablet mode.
-TEST_F(WindowFloatTest, FloatWindowUnfloatsEnterTablet) {
+TEST_F(TabletWindowFloatTest, FloatWindowUnfloatsEnterTablet) {
   UpdateDisplay("800x600");
 
   aura::test::TestWindowDelegate window_delegate;
@@ -110,7 +115,7 @@
 
 // Tests that a floated window unfloats if a display change makes it no longer a
 // valid floating window.
-TEST_F(WindowFloatTest, FloatWindowUnfloatsDisplayChange) {
+TEST_F(TabletWindowFloatTest, FloatWindowUnfloatsDisplayChange) {
   UpdateDisplay("1800x1000");
 
   aura::test::TestWindowDelegate window_delegate;
@@ -133,7 +138,7 @@
 
 // Tests that windows floated in tablet mode have immersive mode disabled,
 // showing their title bars.
-TEST_F(WindowFloatTest, TabletImmersiveMode) {
+TEST_F(TabletWindowFloatTest, ImmersiveMode) {
   // Create a test app window that has a header.
   auto window = CreateAppWindow();
   auto* immersive_controller = chromeos::ImmersiveFullscreenController::Get(
@@ -153,4 +158,51 @@
   // to tablet from clamshell and vice versa.
 }
 
+TEST_F(TabletWindowFloatTest, Rotation) {
+  // Use a display where the width and height are quite different, otherwise it
+  // would be hard to tell if portrait mode is using landscape bounds to
+  // calculate floating window bounds.
+  UpdateDisplay("1800x1000");
+
+  std::unique_ptr<aura::Window> window = CreateTestWindow();
+  wm::ActivateWindow(window.get());
+
+  // Enter tablet mode and float `window`.
+  Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
+  PressAndReleaseKey(ui::VKEY_F, ui::EF_ALT_DOWN | ui::EF_COMMAND_DOWN);
+  ASSERT_TRUE(Shell::Get()->float_controller()->IsFloated(window.get()));
+  const gfx::Rect no_rotation_bounds = window->bounds();
+
+  // Set the primary display as the internal display so that the orientation
+  // controller can rotate it.
+  display::test::ScopedSetInternalDisplayId scoped_set_internal(
+      Shell::Get()->display_manager(),
+      display::Screen::GetScreen()->GetPrimaryDisplay().id());
+  ScreenOrientationControllerTestApi orientation_test_api(
+      Shell::Get()->screen_orientation_controller());
+
+  // First rotate to landscape secondary orientation. The float bounds should
+  // be the same.
+  orientation_test_api.SetDisplayRotation(
+      display::Display::ROTATE_180, display::Display::RotationSource::ACTIVE);
+  EXPECT_EQ(window->bounds(), no_rotation_bounds);
+
+  // Rotate to the two portrait orientations. The float bounds should be
+  // similar since landscape bounds are used for portrait float calculations
+  // as well, but slightly different since the shelf affects the work area
+  // differently.
+  const int shelf_size = ShelfConfig::Get()->shelf_size();
+  orientation_test_api.SetDisplayRotation(
+      display::Display::ROTATE_90, display::Display::RotationSource::ACTIVE);
+  EXPECT_NEAR(no_rotation_bounds.width(), window->bounds().width(), shelf_size);
+  EXPECT_NEAR(no_rotation_bounds.height(), window->bounds().height(),
+              shelf_size);
+
+  orientation_test_api.SetDisplayRotation(
+      display::Display::ROTATE_270, display::Display::RotationSource::ACTIVE);
+  EXPECT_NEAR(no_rotation_bounds.width(), window->bounds().width(), shelf_size);
+  EXPECT_NEAR(no_rotation_bounds.height(), window->bounds().height(),
+              shelf_size);
+}
+
 }  // namespace ash
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc
index f9f633a9..bddae2a 100644
--- a/base/process/process_posix.cc
+++ b/base/process/process_posix.cc
@@ -326,6 +326,21 @@
   DCHECK(IsValid());
   CHECK_GT(process_, 0);
 
+  // RESULT_CODE_KILLED_BAD_MESSAGE == 3, but layering prevents its use.
+  // |wait| is always false when terminating badly-behaved processes.
+  const bool maybe_compromised = !wait && exit_code == 3;
+  if (maybe_compromised) {
+    // Forcibly terminate the process immediately.
+    const bool was_killed = kill(process_, SIGKILL) != 0;
+#if BUILDFLAG(IS_CHROMEOS)
+    if (was_killed)
+      CleanUpProcessAsync();
+#endif
+    DPLOG_IF(ERROR, !was_killed) << "Unable to terminate process " << process_;
+    return was_killed;
+  }
+
+  // Terminate process giving it a chance to clean up.
   if (kill(process_, SIGTERM) != 0) {
     DPLOG(ERROR) << "Unable to terminate process " << process_;
     return false;
diff --git a/chrome/VERSION b/chrome/VERSION
index 1a26532..8e52c224 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=105
 MINOR=0
-BUILD=5147
+BUILD=5148
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 75fbdd9..be3355b4 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -672,6 +672,7 @@
     ":vr_build_config",
     "//chrome:instant_apps_reasons_enum_javagen",
     "//chrome:offline_pages_enum_javagen",
+    "//chrome:partner_bookmarks_javagen",
     "//chrome:quick_action_category_enum_javagen",
     "//chrome:supervised_user_url_filter_enum_javagen",
     "//chrome/browser:screenshot_mode_enum",
@@ -1031,7 +1032,6 @@
     "//chrome/browser/omaha/android:java",
     "//chrome/browser/optimization_guide/android:java",
     "//chrome/browser/page_annotations/test/android:junit",
-    "//chrome/browser/partnerbookmarks:junit",
     "//chrome/browser/partnercustomizations:java",
     "//chrome/browser/password_edit_dialog/android:junit",
     "//chrome/browser/password_entry_edit/android/internal:junit",
@@ -4134,6 +4134,7 @@
     "java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTask.java",
     "java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchBackgroundTaskScheduler.java",
     "java/src/org/chromium/chrome/browser/page_info/PageInfoAboutThisSiteController.java",
+    "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java",
     "java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java",
     "java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java",
     "java/src/org/chromium/chrome/browser/password_manager/AutoSigninSnackbarController.java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index ebf5aa6..b133b84 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -400,6 +400,7 @@
   "java/res/drawable/ic_google_services_48dp.xml",
   "java/res/drawable/ic_image_descriptions.xml",
   "java/res/drawable/ic_incognito_cct_24dp.xml",
+  "java/res/drawable/ic_incognito_reauth_promo_icon.xml",
   "java/res/drawable/ic_new_tab_button.xml",
   "java/res/drawable/ic_new_window.xml",
   "java/res/drawable/ic_offer_tag.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 045d72a..82b9ee0 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -865,6 +865,10 @@
   "java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java",
   "java/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelper.java",
   "java/src/org/chromium/chrome/browser/paint_preview/StartupPaintPreviewHelperSupplier.java",
+  "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java",
+  "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java",
+  "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java",
+  "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java",
   "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java",
   "java/src/org/chromium/chrome/browser/password_manager/AccountChooserDialog.java",
   "java/src/org/chromium/chrome/browser/password_manager/AutoSigninFirstRunDialog.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
index ad30221..3e15792 100644
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -196,6 +196,8 @@
   "junit/src/org/chromium/chrome/browser/omaha/metrics/UpdateSuccessMetricsTest.java",
   "junit/src/org/chromium/chrome/browser/page_info/PageInfoPermissionsControllerUnitTest.java",
   "junit/src/org/chromium/chrome/browser/page_info/PermissionParamsListBuilderUnitTest.java",
+  "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java",
+  "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java",
   "junit/src/org/chromium/chrome/browser/password_manager/settings/DialogManagerTest.java",
   "junit/src/org/chromium/chrome/browser/password_manager/settings/EnsureAsyncPostingRule.java",
   "junit/src/org/chromium/chrome/browser/password_manager/settings/ExportWarningDialogFragmentTest.java",
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 ddaab17..11502c5d0 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
@@ -1436,7 +1436,6 @@
     @Test
     @MediumTest
     // clang-format off
-    @DisabledTest(message = "https://crbug.com/1335780")
     @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
             ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID + "<Study"})
     @CommandLineFlags.Add({BASE_PARAMS + "/enable_launch_polish/true"})
@@ -1574,7 +1573,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "https://crbug.com/1333098")
     @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
     public void testTabGroupManualSelection_DisabledForSingleTab() {
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogCoordinator.java
index ccff112d..edddf8b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogCoordinator.java
@@ -9,6 +9,7 @@
 import android.widget.CompoundButton;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 
+import org.chromium.base.TraceEvent;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManager;
 import org.chromium.chrome.browser.price_tracking.PriceTrackingUtilities;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -30,36 +31,41 @@
             TabSwitcherMediator.ResetHandler resetHandler, TabModelSelector tabModelSelector,
             PriceDropNotificationManager notificationManager,
             @TabListCoordinator.TabListMode int mode) {
-        mDialogView = (PriceTrackingDialogView) LayoutInflater.from(context).inflate(
-                R.layout.price_tracking_dialog_layout, null, false);
-        mDialogView.setupTrackPricesSwitchOnCheckedChangeListener(this);
-        mDialogView.setupPriceAlertsArrowOnClickListener(
-                v -> { notificationManager.launchNotificationSettings(); });
-        mModalDialogManager = modalDialogManager;
+        try (TraceEvent e = TraceEvent.scoped("PriceTrackingDialogCoordinator.constructor")) {
+            mDialogView = (PriceTrackingDialogView) LayoutInflater.from(context).inflate(
+                    R.layout.price_tracking_dialog_layout, null, false);
+            mDialogView.setupTrackPricesSwitchOnCheckedChangeListener(this);
+            mDialogView.setupPriceAlertsArrowOnClickListener(
+                    v -> { notificationManager.launchNotificationSettings(); });
+            mModalDialogManager = modalDialogManager;
 
-        ModalDialogProperties.Controller dialogController = new ModalDialogProperties.Controller() {
-            @Override
-            public void onClick(PropertyModel model, int buttonType) {}
+            ModalDialogProperties.Controller dialogController =
+                    new ModalDialogProperties.Controller() {
+                        @Override
+                        public void onClick(PropertyModel model, int buttonType) {}
 
-            @Override
-            public void onDismiss(PropertyModel model, int dismissalCause) {
-                if (dismissalCause == DialogDismissalCause.ACTIVITY_DESTROYED) return;
+                        @Override
+                        public void onDismiss(PropertyModel model, int dismissalCause) {
+                            if (dismissalCause == DialogDismissalCause.ACTIVITY_DESTROYED) return;
 
-                // We only need to call resetWithTabList under GRID tab switcher. For now it's used
-                // to show/hide price drop cards on tabs timely.
-                if (mode == TabListCoordinator.TabListMode.GRID) {
-                    resetHandler.resetWithTabList(
-                            tabModelSelector.getTabModelFilterProvider().getCurrentTabModelFilter(),
-                            false, TabSwitcherCoordinator.isShowingTabsInMRUOrder(mode));
-                }
-            }
-        };
+                            // We only need to call resetWithTabList under GRID tab switcher. For
+                            // now it's used to show/hide price drop cards on tabs timely.
+                            if (mode == TabListCoordinator.TabListMode.GRID) {
+                                resetHandler.resetWithTabList(
+                                        tabModelSelector.getTabModelFilterProvider()
+                                                .getCurrentTabModelFilter(),
+                                        false,
+                                        TabSwitcherCoordinator.isShowingTabsInMRUOrder(mode));
+                            }
+                        }
+                    };
 
-        mModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
-                         .with(ModalDialogProperties.CONTROLLER, dialogController)
-                         .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
-                         .with(ModalDialogProperties.CUSTOM_VIEW, mDialogView)
-                         .build();
+            mModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
+                             .with(ModalDialogProperties.CONTROLLER, dialogController)
+                             .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
+                             .with(ModalDialogProperties.CUSTOM_VIEW, mDialogView)
+                             .build();
+        }
     }
 
     void show() {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
index 8fadd57..8aaf09b0 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogCoordinator.java
@@ -14,6 +14,7 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.SysUtils;
+import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.ObservableSupplierImpl;
@@ -55,71 +56,75 @@
             TabGridDialogMediator.AnimationSourceViewProvider animationSourceViewProvider,
             Supplier<ShareDelegate> shareDelegateSupplier, ScrimCoordinator scrimCoordinator,
             ViewGroup rootView) {
-        mComponentName = animationSourceViewProvider == null ? "TabGridDialogFromStrip"
-                                                             : "TabGridDialogInSwitcher";
+        try (TraceEvent e = TraceEvent.scoped("TabGridDialogCoordinator.constructor")) {
+            mComponentName = animationSourceViewProvider == null ? "TabGridDialogFromStrip"
+                                                                 : "TabGridDialogInSwitcher";
 
-        mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS);
-        mRootView = rootView;
+            mModel = new PropertyModel(TabGridPanelProperties.ALL_KEYS);
+            mRootView = rootView;
 
-        mDialogView = containerView.findViewById(R.id.dialog_parent_view);
-        if (mDialogView == null) {
-            LayoutInflater.from(activity).inflate(
-                    R.layout.tab_grid_dialog_layout, containerView, true);
             mDialogView = containerView.findViewById(R.id.dialog_parent_view);
-            mDialogView.setupScrimCoordinator(scrimCoordinator);
+            if (mDialogView == null) {
+                LayoutInflater.from(activity).inflate(
+                        R.layout.tab_grid_dialog_layout, containerView, true);
+                mDialogView = containerView.findViewById(R.id.dialog_parent_view);
+                mDialogView.setupScrimCoordinator(scrimCoordinator);
+            }
+            SnackbarManager snackbarManager =
+                    new SnackbarManager(activity, mDialogView.getSnackBarContainer(), null);
+
+            mMediator = new TabGridDialogMediator(activity, this, mModel, tabModelSelector,
+                    tabCreatorManager, resetHandler, animationSourceViewProvider,
+                    shareDelegateSupplier, snackbarManager, mComponentName);
+
+            // TODO(crbug.com/1031349) : Remove the inline mode logic here, make the constructor to
+            // take in a mode parameter instead.
+            mTabListCoordinator = new TabListCoordinator(
+                    TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)
+                                    && SysUtils.isLowEndDevice()
+                            ? TabListCoordinator.TabListMode.LIST
+                            : TabListCoordinator.TabListMode.GRID,
+                    activity, tabModelSelector, tabContentManager::getTabThumbnailWithCallback,
+                    null, false, gridCardOnClickListenerProvider,
+                    mMediator.getTabGridDialogHandler(), TabProperties.UiType.CLOSABLE, null, null,
+                    containerView, false, mComponentName, rootView);
+            TabListRecyclerView recyclerView = mTabListCoordinator.getContainerView();
+
+            TabGroupUiToolbarView toolbarView =
+                    (TabGroupUiToolbarView) LayoutInflater.from(activity).inflate(
+                            R.layout.bottom_tab_grid_toolbar, recyclerView, false);
+            toolbarView.setupDialogToolbarLayout();
+            if (!TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)) {
+                toolbarView.hideTabGroupsContinuationWidgets();
+            }
+            mModelChangeProcessor = PropertyModelChangeProcessor.create(mModel,
+                    new TabGridPanelViewBinder.ViewHolder(toolbarView, recyclerView, mDialogView),
+                    TabGridPanelViewBinder::bind);
+            mBackPressChangedSupplier.set(isVisible());
+            mModel.addObserver((source, key) -> mBackPressChangedSupplier.set(isVisible()));
         }
-        SnackbarManager snackbarManager =
-                new SnackbarManager(activity, mDialogView.getSnackBarContainer(), null);
-
-        mMediator = new TabGridDialogMediator(activity, this, mModel, tabModelSelector,
-                tabCreatorManager, resetHandler, animationSourceViewProvider, shareDelegateSupplier,
-                snackbarManager, mComponentName);
-
-        // TODO(crbug.com/1031349) : Remove the inline mode logic here, make the constructor to take
-        // in a mode parameter instead.
-        mTabListCoordinator = new TabListCoordinator(
-                TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)
-                                && SysUtils.isLowEndDevice()
-                        ? TabListCoordinator.TabListMode.LIST
-                        : TabListCoordinator.TabListMode.GRID,
-                activity, tabModelSelector, tabContentManager::getTabThumbnailWithCallback, null,
-                false, gridCardOnClickListenerProvider, mMediator.getTabGridDialogHandler(),
-                TabProperties.UiType.CLOSABLE, null, null, containerView, false, mComponentName,
-                rootView);
-        TabListRecyclerView recyclerView = mTabListCoordinator.getContainerView();
-
-        TabGroupUiToolbarView toolbarView =
-                (TabGroupUiToolbarView) LayoutInflater.from(activity).inflate(
-                        R.layout.bottom_tab_grid_toolbar, recyclerView, false);
-        toolbarView.setupDialogToolbarLayout();
-        if (!TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)) {
-            toolbarView.hideTabGroupsContinuationWidgets();
-        }
-        mModelChangeProcessor = PropertyModelChangeProcessor.create(mModel,
-                new TabGridPanelViewBinder.ViewHolder(toolbarView, recyclerView, mDialogView),
-                TabGridPanelViewBinder::bind);
-        mBackPressChangedSupplier.set(isVisible());
-        mModel.addObserver((source, key) -> mBackPressChangedSupplier.set(isVisible()));
     }
 
     public void initWithNative(Context context, TabModelSelector tabModelSelector,
             TabContentManager tabContentManager, TabGroupTitleEditor tabGroupTitleEditor) {
-        TabSelectionEditorCoordinator.TabSelectionEditorController controller = null;
-        if (TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(context)) {
-            @TabListCoordinator.TabListMode
-            int mode = SysUtils.isLowEndDevice() ? TabListCoordinator.TabListMode.LIST
-                                                 : TabListCoordinator.TabListMode.GRID;
-            mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(context,
-                    mDialogView.findViewById(R.id.dialog_container_view), tabModelSelector,
-                    tabContentManager, mode, mRootView);
+        try (TraceEvent e = TraceEvent.scoped("TabGridDialogCoordinator.initWithNative")) {
+            TabSelectionEditorCoordinator.TabSelectionEditorController controller = null;
+            if (TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(context)) {
+                @TabListCoordinator.TabListMode
+                int mode = SysUtils.isLowEndDevice() ? TabListCoordinator.TabListMode.LIST
+                                                     : TabListCoordinator.TabListMode.GRID;
+                mTabSelectionEditorCoordinator = new TabSelectionEditorCoordinator(context,
+                        mDialogView.findViewById(R.id.dialog_container_view), tabModelSelector,
+                        tabContentManager, mode, mRootView);
 
-            controller = mTabSelectionEditorCoordinator.getController();
-        } else {
-            mTabSelectionEditorCoordinator = null;
+                controller = mTabSelectionEditorCoordinator.getController();
+            } else {
+                mTabSelectionEditorCoordinator = null;
+            }
+
+            mMediator.initWithNative(controller, tabGroupTitleEditor);
+            mTabListCoordinator.initWithNative(null);
         }
-
-        mMediator.initWithNative(controller, tabGroupTitleEditor);
-        mTabListCoordinator.initWithNative(null);
     }
     /**
      * Destroy any members that needs clean up.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphDialogCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphDialogCoordinator.java
index bc164a5..c064e41 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphDialogCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphDialogCoordinator.java
@@ -10,6 +10,7 @@
 import android.view.ViewGroup;
 import android.view.ViewTreeObserver;
 
+import org.chromium.base.TraceEvent;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.ui.modaldialog.DialogDismissalCause;
 import org.chromium.ui.modaldialog.ModalDialogManager;
@@ -28,36 +29,39 @@
 
     TabGridIphDialogCoordinator(
             Context context, ViewGroup parent, ModalDialogManager modalDialogManager) {
-        mIphDialogView = (TabGridIphDialogView) LayoutInflater.from(context).inflate(
-                R.layout.iph_drag_and_drop_dialog_layout, null, false);
-        mModalDialogManager = modalDialogManager;
-        mParentView = parent;
+        try (TraceEvent e = TraceEvent.scoped("TabGridIphDialogCoordinator.constructor")) {
+            mIphDialogView = (TabGridIphDialogView) LayoutInflater.from(context).inflate(
+                    R.layout.iph_drag_and_drop_dialog_layout, null, false);
+            mModalDialogManager = modalDialogManager;
+            mParentView = parent;
 
-        ModalDialogProperties.Controller dialogController = new ModalDialogProperties.Controller() {
-            @Override
-            public void onClick(PropertyModel model, int buttonType) {
-                if (buttonType == ModalDialogProperties.ButtonType.POSITIVE) {
-                    modalDialogManager.dismissDialog(
-                            model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED);
-                }
-            }
+            ModalDialogProperties.Controller dialogController =
+                    new ModalDialogProperties.Controller() {
+                        @Override
+                        public void onClick(PropertyModel model, int buttonType) {
+                            if (buttonType == ModalDialogProperties.ButtonType.POSITIVE) {
+                                modalDialogManager.dismissDialog(
+                                        model, DialogDismissalCause.POSITIVE_BUTTON_CLICKED);
+                            }
+                        }
 
-            @Override
-            public void onDismiss(PropertyModel model, int dismissalCause) {
-                mIphDialogView.stopIPHAnimation();
-            }
-        };
-        mModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
-                         .with(ModalDialogProperties.CONTROLLER, dialogController)
-                         .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
-                         .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
-                                 context.getResources().getString(R.string.ok))
-                         .with(ModalDialogProperties.CUSTOM_VIEW, mIphDialogView)
-                         .build();
+                        @Override
+                        public void onDismiss(PropertyModel model, int dismissalCause) {
+                            mIphDialogView.stopIPHAnimation();
+                        }
+                    };
+            mModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
+                             .with(ModalDialogProperties.CONTROLLER, dialogController)
+                             .with(ModalDialogProperties.CANCEL_ON_TOUCH_OUTSIDE, true)
+                             .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
+                                     context.getResources().getString(R.string.ok))
+                             .with(ModalDialogProperties.CUSTOM_VIEW, mIphDialogView)
+                             .build();
 
-        mIphDialogView.setRootView(mParentView);
-        mRootViewLayoutListener = mIphDialogView::updateLayout;
-        mParentView.getViewTreeObserver().addOnGlobalLayoutListener(mRootViewLayoutListener);
+            mIphDialogView.setRootView(mParentView);
+            mRootViewLayoutListener = mIphDialogView::updateLayout;
+            mParentView.getViewTreeObserver().addOnGlobalLayoutListener(mRootViewLayoutListener);
+        }
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
index 97a729e..605cd6e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -14,6 +14,7 @@
 
 import androidx.annotation.NonNull;
 
+import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
@@ -99,28 +100,30 @@
             @NonNull Supplier<ShareDelegate> shareDelegateSupplier,
             @NonNull OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier,
             @NonNull SnackbarManager snackbarManager) {
-        mActivity = activity;
-        mContext = parentView.getContext();
-        mIncognitoStateProvider = incognitoStateProvider;
-        mScrimCoordinator = scrimCoordinator;
-        mOmniboxFocusStateSupplier = omniboxFocusStateSupplier;
-        mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS);
-        mToolbarView = (TabGroupUiToolbarView) LayoutInflater.from(mContext).inflate(
-                R.layout.bottom_tab_strip_toolbar, parentView, false);
-        mTabListContainerView = mToolbarView.getViewContainer();
-        mBottomSheetController = bottomSheetController;
-        mActivityLifecycleDispatcher = activityLifecycleDispatcher;
-        mActivityLifecycleDispatcher.register(this);
-        mIsWarmOnResumeSupplier = isWarmOnResumeSupplier;
-        mTabModelSelector = tabModelSelector;
-        mLayoutStateProviderSupplier = layoutStateProviderSupplier;
-        mRootView = rootView;
-        mSnackbarManager = snackbarManager;
-        mShareDelegateSupplier = shareDelegateSupplier;
-        mTabCreatorManager = tabCreatorManager;
-        mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier;
-        mTabContentManager = tabContentManager;
-        parentView.addView(mToolbarView);
+        try (TraceEvent e = TraceEvent.scoped("TabGroupUiCoordinator.constructor")) {
+            mActivity = activity;
+            mContext = parentView.getContext();
+            mIncognitoStateProvider = incognitoStateProvider;
+            mScrimCoordinator = scrimCoordinator;
+            mOmniboxFocusStateSupplier = omniboxFocusStateSupplier;
+            mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS);
+            mToolbarView = (TabGroupUiToolbarView) LayoutInflater.from(mContext).inflate(
+                    R.layout.bottom_tab_strip_toolbar, parentView, false);
+            mTabListContainerView = mToolbarView.getViewContainer();
+            mBottomSheetController = bottomSheetController;
+            mActivityLifecycleDispatcher = activityLifecycleDispatcher;
+            mActivityLifecycleDispatcher.register(this);
+            mIsWarmOnResumeSupplier = isWarmOnResumeSupplier;
+            mTabModelSelector = tabModelSelector;
+            mLayoutStateProviderSupplier = layoutStateProviderSupplier;
+            mRootView = rootView;
+            mSnackbarManager = snackbarManager;
+            mShareDelegateSupplier = shareDelegateSupplier;
+            mTabCreatorManager = tabCreatorManager;
+            mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier;
+            mTabContentManager = tabContentManager;
+            parentView.addView(mToolbarView);
+        }
     }
 
     /**
@@ -129,59 +132,61 @@
     @Override
     public void initializeWithNative(Activity activity,
             BottomControlsCoordinator.BottomControlsVisibilityController visibilityController) {
-        if (UmaSessionStats.isMetricsServiceAvailable()) {
-            UmaSessionStats.registerSyntheticFieldTrial(
-                    ChromeFeatureList.TAB_GROUPS_ANDROID + SYNTHETIC_TRIAL_POSTFIX,
-                    "Downloaded_Enabled");
-        }
-
-        boolean actionOnAllRelatedTabs = TabUiFeatureUtilities.isConditionalTabStripEnabled();
-        mTabStripCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.STRIP,
-                mContext, mTabModelSelector, null, null, actionOnAllRelatedTabs, null, null,
-                TabProperties.UiType.STRIP, null, null, mTabListContainerView, true, COMPONENT_NAME,
-                mRootView);
-        mTabStripCoordinator.initWithNative(mDynamicResourceLoaderSupplier.get());
-
-        mModelChangeProcessor = PropertyModelChangeProcessor.create(mModel,
-                new TabGroupUiViewBinder.ViewHolder(
-                        mToolbarView, mTabStripCoordinator.getContainerView()),
-                TabGroupUiViewBinder::bind);
-
-        // TODO(crbug.com/972217): find a way to enable interactions between grid tab switcher
-        //  and the dialog here.
-        TabGridDialogMediator.DialogController dialogController = null;
-        if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)
-                && mScrimCoordinator != null) {
-            mTabGridDialogCoordinator =
-                    new TabGridDialogCoordinator(mActivity, mTabModelSelector, mTabContentManager,
-                            mTabCreatorManager, mActivity.findViewById(R.id.coordinator), null,
-                            null, null, mShareDelegateSupplier, mScrimCoordinator, mRootView);
-            mTabGridDialogCoordinator.initWithNative(mContext, mTabModelSelector,
-                    mTabContentManager, mTabStripCoordinator.getTabGroupTitleEditor());
-            dialogController = mTabGridDialogCoordinator.getDialogController();
-        }
-
-        mMediator = new TabGroupUiMediator(mActivity, visibilityController, this, mModel,
-                mTabModelSelector, mTabCreatorManager, mLayoutStateProviderSupplier,
-                mIncognitoStateProvider, dialogController, mActivityLifecycleDispatcher,
-                mSnackbarManager, mOmniboxFocusStateSupplier);
-
-        TabGroupUtils.startObservingForCreationIPH();
-
-        if (TabUiFeatureUtilities.isConditionalTabStripEnabled()) return;
-
-        // TODO(meiliang): Potential leak if the observer is added after restoreCompleted. Fix it.
-        // Record the group count after all tabs are being restored. This only happen once per life
-        // cycle, therefore remove the observer after recording. We only focus on normal tab model
-        // because we don't restore tabs in incognito tab model.
-        mTabModelSelector.getModel(false).addObserver(new TabModelObserver() {
-            @Override
-            public void restoreCompleted() {
-                recordTabGroupCount();
-                recordSessionCount();
-                mTabModelSelector.getModel(false).removeObserver(this);
+        try (TraceEvent e = TraceEvent.scoped("TabGroupUiCoordinator.initializeWithNative")) {
+            if (UmaSessionStats.isMetricsServiceAvailable()) {
+                UmaSessionStats.registerSyntheticFieldTrial(
+                        ChromeFeatureList.TAB_GROUPS_ANDROID + SYNTHETIC_TRIAL_POSTFIX,
+                        "Downloaded_Enabled");
             }
-        });
+
+            boolean actionOnAllRelatedTabs = TabUiFeatureUtilities.isConditionalTabStripEnabled();
+            mTabStripCoordinator = new TabListCoordinator(TabListCoordinator.TabListMode.STRIP,
+                    mContext, mTabModelSelector, null, null, actionOnAllRelatedTabs, null, null,
+                    TabProperties.UiType.STRIP, null, null, mTabListContainerView, true,
+                    COMPONENT_NAME, mRootView);
+            mTabStripCoordinator.initWithNative(mDynamicResourceLoaderSupplier.get());
+
+            mModelChangeProcessor = PropertyModelChangeProcessor.create(mModel,
+                    new TabGroupUiViewBinder.ViewHolder(
+                            mToolbarView, mTabStripCoordinator.getContainerView()),
+                    TabGroupUiViewBinder::bind);
+
+            // TODO(crbug.com/972217): find a way to enable interactions between grid tab switcher
+            //  and the dialog here.
+            TabGridDialogMediator.DialogController dialogController = null;
+            if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)
+                    && mScrimCoordinator != null) {
+                mTabGridDialogCoordinator = new TabGridDialogCoordinator(mActivity,
+                        mTabModelSelector, mTabContentManager, mTabCreatorManager,
+                        mActivity.findViewById(R.id.coordinator), null, null, null,
+                        mShareDelegateSupplier, mScrimCoordinator, mRootView);
+                mTabGridDialogCoordinator.initWithNative(mContext, mTabModelSelector,
+                        mTabContentManager, mTabStripCoordinator.getTabGroupTitleEditor());
+                dialogController = mTabGridDialogCoordinator.getDialogController();
+            }
+
+            mMediator = new TabGroupUiMediator(mActivity, visibilityController, this, mModel,
+                    mTabModelSelector, mTabCreatorManager, mLayoutStateProviderSupplier,
+                    mIncognitoStateProvider, dialogController, mActivityLifecycleDispatcher,
+                    mSnackbarManager, mOmniboxFocusStateSupplier);
+
+            TabGroupUtils.startObservingForCreationIPH();
+
+            if (TabUiFeatureUtilities.isConditionalTabStripEnabled()) return;
+
+            // TODO(meiliang): Potential leak if the observer is added after restoreCompleted. Fix
+            // it. Record the group count after all tabs are being restored. This only happen once
+            // per life cycle, therefore remove the observer after recording. We only focus on
+            // normal tab model because we don't restore tabs in incognito tab model.
+            mTabModelSelector.getModel(false).addObserver(new TabModelObserver() {
+                @Override
+                public void restoreCompleted() {
+                    recordTabGroupCount();
+                    recordSessionCount();
+                    mTabModelSelector.getModel(false).removeObserver(this);
+                }
+            });
+        }
     }
 
     /**
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 adb9627..df5f6ed 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
@@ -24,6 +24,7 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import org.chromium.base.TraceEvent;
 import org.chromium.chrome.browser.lifecycle.DestroyObserver;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
@@ -213,25 +214,6 @@
                     "Attempting to create a tab list UI with invalid mode");
         }
 
-        if (!attachToParent) {
-            mRecyclerView = (TabListRecyclerView) LayoutInflater.from(context).inflate(
-                    R.layout.tab_list_recycler_view_layout, parentView, false);
-        } else {
-            LayoutInflater.from(context).inflate(
-                    R.layout.tab_list_recycler_view_layout, parentView, true);
-            mRecyclerView = parentView.findViewById(R.id.tab_list_view);
-        }
-
-        if (mode == TabListMode.CAROUSEL) {
-            ViewGroup.LayoutParams layoutParams = mRecyclerView.getLayoutParams();
-            layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
-            mRecyclerView.setLayoutParams(layoutParams);
-        }
-
-        mRecyclerView.setAdapter(mAdapter);
-        mRecyclerView.setHasFixedSize(true);
-        if (recyclerListener != null) mRecyclerView.setRecyclerListener(recyclerListener);
-
         // TODO (https://crbug.com/1048632): Use the current profile (i.e., regular profile or
         // incognito profile) instead of always using regular profile. It works correctly now, but
         // it is not safe.
@@ -243,21 +225,42 @@
                 selectionDelegateProvider, gridCardOnClickListenerProvider, dialogHandler,
                 priceWelcomeMessageController, componentName, itemType);
 
-        if (mMode == TabListMode.GRID) {
-            GridLayoutManager gridLayoutManager =
-                    new GridLayoutManager(context, GRID_LAYOUT_SPAN_COUNT_COMPACT);
-            mRecyclerView.setLayoutManager(gridLayoutManager);
-            mMediator.registerOrientationListener(gridLayoutManager);
-            mMediator.updateSpanCount(gridLayoutManager,
-                    context.getResources().getConfiguration().orientation,
-                    context.getResources().getConfiguration().screenWidthDp);
-            mMediator.setupAccessibilityDelegate(mRecyclerView);
-        } else if (mMode == TabListMode.STRIP || mMode == TabListMode.CAROUSEL
-                || mMode == TabListMode.LIST) {
-            mRecyclerView.setLayoutManager(new LinearLayoutManager(context,
-                    mMode == TabListMode.LIST ? LinearLayoutManager.VERTICAL
-                                              : LinearLayoutManager.HORIZONTAL,
-                    false));
+        try (TraceEvent e = TraceEvent.scoped("TabListCoordinator.setupRecyclerView")) {
+            if (!attachToParent) {
+                mRecyclerView = (TabListRecyclerView) LayoutInflater.from(context).inflate(
+                        R.layout.tab_list_recycler_view_layout, parentView, false);
+            } else {
+                LayoutInflater.from(context).inflate(
+                        R.layout.tab_list_recycler_view_layout, parentView, true);
+                mRecyclerView = parentView.findViewById(R.id.tab_list_view);
+            }
+
+            if (mode == TabListMode.CAROUSEL) {
+                ViewGroup.LayoutParams layoutParams = mRecyclerView.getLayoutParams();
+                layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+                mRecyclerView.setLayoutParams(layoutParams);
+            }
+
+            mRecyclerView.setAdapter(mAdapter);
+            mRecyclerView.setHasFixedSize(true);
+            if (recyclerListener != null) mRecyclerView.setRecyclerListener(recyclerListener);
+
+            if (mMode == TabListMode.GRID) {
+                GridLayoutManager gridLayoutManager =
+                        new GridLayoutManager(context, GRID_LAYOUT_SPAN_COUNT_COMPACT);
+                mRecyclerView.setLayoutManager(gridLayoutManager);
+                mMediator.registerOrientationListener(gridLayoutManager);
+                mMediator.updateSpanCount(gridLayoutManager,
+                        context.getResources().getConfiguration().orientation,
+                        context.getResources().getConfiguration().screenWidthDp);
+                mMediator.setupAccessibilityDelegate(mRecyclerView);
+            } else if (mMode == TabListMode.STRIP || mMode == TabListMode.CAROUSEL
+                    || mMode == TabListMode.LIST) {
+                mRecyclerView.setLayoutManager(new LinearLayoutManager(context,
+                        mMode == TabListMode.LIST ? LinearLayoutManager.VERTICAL
+                                                  : LinearLayoutManager.HORIZONTAL,
+                        false));
+            }
         }
 
         if (mMode == TabListMode.GRID && selectionDelegateProvider == null) {
@@ -285,25 +288,30 @@
     void initWithNative(DynamicResourceLoader dynamicResourceLoader) {
         if (mIsInitialized) return;
 
-        mIsInitialized = true;
+        try (TraceEvent e = TraceEvent.scoped("TabListCoordinator.initWithNative")) {
+            mIsInitialized = true;
 
-        Profile profile = Profile.getLastUsedRegularProfile();
-        mMediator.initWithNative(profile);
-        if (dynamicResourceLoader != null) {
-            mRecyclerView.createDynamicView(dynamicResourceLoader);
-        }
+            Profile profile = Profile.getLastUsedRegularProfile();
+            mMediator.initWithNative(profile);
+            if (dynamicResourceLoader != null) {
+                mRecyclerView.createDynamicView(dynamicResourceLoader);
+            }
 
-        if ((mMode == TabListMode.GRID || mMode == TabListMode.LIST)
-                && mItemType != UiType.SELECTABLE) {
-            ItemTouchHelper touchHelper = new ItemTouchHelper(mMediator.getItemTouchHelperCallback(
-                    mContext.getResources().getDimension(R.dimen.swipe_to_dismiss_threshold),
-                    mContext.getResources().getDimension(R.dimen.tab_grid_merge_threshold),
-                    mContext.getResources().getDimension(R.dimen.bottom_sheet_peek_height),
-                    profile));
-            touchHelper.attachToRecyclerView(mRecyclerView);
+            if ((mMode == TabListMode.GRID || mMode == TabListMode.LIST)
+                    && mItemType != UiType.SELECTABLE) {
+                ItemTouchHelper touchHelper =
+                        new ItemTouchHelper(mMediator.getItemTouchHelperCallback(
+                                mContext.getResources().getDimension(
+                                        R.dimen.swipe_to_dismiss_threshold),
+                                mContext.getResources().getDimension(
+                                        R.dimen.tab_grid_merge_threshold),
+                                mContext.getResources().getDimension(
+                                        R.dimen.bottom_sheet_peek_height),
+                                profile));
+                touchHelper.attachToRecyclerView(mRecyclerView);
+            }
         }
     }
-
     /**
      * Update the location of the selected thumbnail.
      * @return Whether a valid {@link Rect} is obtained.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
index 8ba8b8e..4bce528 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorCoordinator.java
@@ -16,6 +16,7 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
+import org.chromium.base.TraceEvent;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
@@ -124,61 +125,65 @@
     public TabSelectionEditorCoordinator(Context context, ViewGroup parentView,
             TabModelSelector tabModelSelector, TabContentManager tabContentManager,
             @TabListMode int mode, ViewGroup rootView) {
-        mContext = context;
-        mParentView = parentView;
-        mTabModelSelector = tabModelSelector;
-        assert mode == TabListCoordinator.TabListMode.GRID
-                || mode == TabListCoordinator.TabListMode.LIST;
+        try (TraceEvent e = TraceEvent.scoped("TabSelectionEditorCoordinator.constructor")) {
+            mContext = context;
+            mParentView = parentView;
+            mTabModelSelector = tabModelSelector;
+            assert mode == TabListCoordinator.TabListMode.GRID
+                    || mode == TabListCoordinator.TabListMode.LIST;
 
-        mTabSelectionEditorLayout =
-                LayoutInflater.from(context)
-                        .inflate(R.layout.tab_selection_editor_layout, parentView, false)
-                        .findViewById(R.id.selectable_list);
+            mTabSelectionEditorLayout =
+                    LayoutInflater.from(context)
+                            .inflate(R.layout.tab_selection_editor_layout, parentView, false)
+                            .findViewById(R.id.selectable_list);
 
-        mTabListCoordinator = new TabListCoordinator(mode, context, mTabModelSelector,
-                tabContentManager::getTabThumbnailWithCallback, null, false, null, null,
-                TabProperties.UiType.SELECTABLE, this::getSelectionDelegate, null,
-                mTabSelectionEditorLayout, false, COMPONENT_NAME, rootView);
+            mTabListCoordinator = new TabListCoordinator(mode, context, mTabModelSelector,
+                    tabContentManager::getTabThumbnailWithCallback, null, false, null, null,
+                    TabProperties.UiType.SELECTABLE, this::getSelectionDelegate, null,
+                    mTabSelectionEditorLayout, false, COMPONENT_NAME, rootView);
 
-        // Note: The TabSelectionEditorCoordinator is always created after native is initialized.
-        assert LibraryLoader.getInstance().isInitialized();
-        mTabListCoordinator.initWithNative(null);
+            // Note: The TabSelectionEditorCoordinator is always created after native is
+            // initialized.
+            assert LibraryLoader.getInstance().isInitialized();
+            mTabListCoordinator.initWithNative(null);
 
-        mTabListCoordinator.registerItemType(TabProperties.UiType.DIVIDER,
-                new LayoutViewBuilder(R.layout.divider_preference),
-                (model, view, propertyKey) -> {});
-        RecyclerView.LayoutManager layoutManager =
-                mTabListCoordinator.getContainerView().getLayoutManager();
-        if (layoutManager instanceof GridLayoutManager) {
-            ((GridLayoutManager) layoutManager)
-                    .setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
-                        @Override
-                        public int getSpanSize(int i) {
-                            int itemType = mTabListCoordinator.getContainerView()
-                                                   .getAdapter()
-                                                   .getItemViewType(i);
+            mTabListCoordinator.registerItemType(TabProperties.UiType.DIVIDER,
+                    new LayoutViewBuilder(R.layout.divider_preference),
+                    (model, view, propertyKey) -> {});
+            RecyclerView.LayoutManager layoutManager =
+                    mTabListCoordinator.getContainerView().getLayoutManager();
+            if (layoutManager instanceof GridLayoutManager) {
+                ((GridLayoutManager) layoutManager)
+                        .setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
+                            @Override
+                            public int getSpanSize(int i) {
+                                int itemType = mTabListCoordinator.getContainerView()
+                                                       .getAdapter()
+                                                       .getItemViewType(i);
 
-                            if (itemType == TabProperties.UiType.DIVIDER) {
-                                return ((GridLayoutManager) layoutManager).getSpanCount();
+                                if (itemType == TabProperties.UiType.DIVIDER) {
+                                    return ((GridLayoutManager) layoutManager).getSpanCount();
+                                }
+                                return 1;
                             }
-                            return 1;
-                        }
-                    });
+                        });
+            }
+
+            mTabSelectionEditorLayout.initialize(mParentView,
+                    mTabListCoordinator.getContainerView(),
+                    mTabListCoordinator.getContainerView().getAdapter(), mSelectionDelegate);
+            mSelectionDelegate.setSelectionModeEnabledForZeroItems(true);
+
+            mModel = new PropertyModel.Builder(TabSelectionEditorProperties.ALL_KEYS)
+                             .with(IS_VISIBLE, false)
+                             .build();
+
+            mTabSelectionEditorLayoutChangeProcessor = PropertyModelChangeProcessor.create(
+                    mModel, mTabSelectionEditorLayout, TabSelectionEditorLayoutBinder::bind, false);
+
+            mTabSelectionEditorMediator = new TabSelectionEditorMediator(mContext,
+                    mTabModelSelector, this::resetWithListOfTabs, mModel, mSelectionDelegate);
         }
-
-        mTabSelectionEditorLayout.initialize(mParentView, mTabListCoordinator.getContainerView(),
-                mTabListCoordinator.getContainerView().getAdapter(), mSelectionDelegate);
-        mSelectionDelegate.setSelectionModeEnabledForZeroItems(true);
-
-        mModel = new PropertyModel.Builder(TabSelectionEditorProperties.ALL_KEYS)
-                         .with(IS_VISIBLE, false)
-                         .build();
-
-        mTabSelectionEditorLayoutChangeProcessor = PropertyModelChangeProcessor.create(
-                mModel, mTabSelectionEditorLayout, TabSelectionEditorLayoutBinder::bind, false);
-
-        mTabSelectionEditorMediator = new TabSelectionEditorMediator(
-                mContext, mTabModelSelector, this::resetWithListOfTabs, mModel, mSelectionDelegate);
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index c57f2864..942bd5e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -18,6 +18,7 @@
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import org.chromium.base.Callback;
+import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
@@ -188,164 +189,170 @@
             @NonNull Supplier<DynamicResourceLoader> dynamicResourceLoaderSupplier,
             @NonNull SnackbarManager snackbarManager,
             @NonNull ModalDialogManager modalDialogManager) {
-        mActivity = activity;
-        mMode = mode;
-        mTabModelSelector = tabModelSelector;
-        mContainer = container;
-        mCoordinatorView = activity.findViewById(R.id.coordinator);
-        mTabCreatorManager = tabCreatorManager;
-        mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
-        mRootView = rootView;
-        mTabContentManager = tabContentManager;
-        mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier;
-        mSnackbarManager = snackbarManager;
-        mModalDialogManager = modalDialogManager;
+        try (TraceEvent e = TraceEvent.scoped("TabSwitcherCoordinator.constructor")) {
+            mActivity = activity;
+            mMode = mode;
+            mTabModelSelector = tabModelSelector;
+            mContainer = container;
+            mCoordinatorView = activity.findViewById(R.id.coordinator);
+            mTabCreatorManager = tabCreatorManager;
+            mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
+            mRootView = rootView;
+            mTabContentManager = tabContentManager;
+            mDynamicResourceLoaderSupplier = dynamicResourceLoaderSupplier;
+            mSnackbarManager = snackbarManager;
+            mModalDialogManager = modalDialogManager;
 
-        PropertyModel containerViewModel = new PropertyModel(TabListContainerProperties.ALL_KEYS);
+            PropertyModel containerViewModel =
+                    new PropertyModel(TabListContainerProperties.ALL_KEYS);
 
-        mMediator = new TabSwitcherMediator(activity, this, containerViewModel, tabModelSelector,
-                browserControls, container, tabContentManager, this, this,
-                multiWindowModeStateDispatcher, mode);
+            mMediator = new TabSwitcherMediator(activity, this, containerViewModel,
+                    tabModelSelector, browserControls, container, tabContentManager, this, this,
+                    multiWindowModeStateDispatcher, mode);
 
-        mTabSwitcherCustomViewManager = new TabSwitcherCustomViewManager(mMediator);
+            mTabSwitcherCustomViewManager = new TabSwitcherCustomViewManager(mMediator);
 
-        mMultiThumbnailCardProvider =
-                new MultiThumbnailCardProvider(activity, tabContentManager, tabModelSelector);
+            mMultiThumbnailCardProvider =
+                    new MultiThumbnailCardProvider(activity, tabContentManager, tabModelSelector);
 
-        PseudoTab.TitleProvider titleProvider = (context, tab) -> {
-            int numRelatedTabs = PseudoTab.getRelatedTabs(context, tab, tabModelSelector).size();
-            if (numRelatedTabs == 1) return tab.getTitle();
-            return activity.getResources().getQuantityString(
-                    R.plurals.bottom_tab_grid_title_placeholder, numRelatedTabs, numRelatedTabs);
-        };
+            PseudoTab.TitleProvider titleProvider = (context, tab) -> {
+                int numRelatedTabs =
+                        PseudoTab.getRelatedTabs(context, tab, tabModelSelector).size();
+                if (numRelatedTabs == 1) return tab.getTitle();
+                return activity.getResources().getQuantityString(
+                        R.plurals.bottom_tab_grid_title_placeholder, numRelatedTabs,
+                        numRelatedTabs);
+            };
 
-        mTabListCoordinator = new TabListCoordinator(mode, activity, tabModelSelector,
-                mMultiThumbnailCardProvider, titleProvider, true, mMediator, null,
-                TabProperties.UiType.CLOSABLE, null, this, container, true, COMPONENT_NAME,
-                mRootView);
-        mContainerViewChangeProcessor = PropertyModelChangeProcessor.create(containerViewModel,
-                mTabListCoordinator.getContainerView(), TabListContainerViewBinder::bind);
+            mTabListCoordinator = new TabListCoordinator(mode, activity, tabModelSelector,
+                    mMultiThumbnailCardProvider, titleProvider, true, mMediator, null,
+                    TabProperties.UiType.CLOSABLE, null, this, container, true, COMPONENT_NAME,
+                    mRootView);
+            mContainerViewChangeProcessor = PropertyModelChangeProcessor.create(containerViewModel,
+                    mTabListCoordinator.getContainerView(), TabListContainerViewBinder::bind);
 
-        mMediator.addTabSwitcherViewObserver(new TabSwitcherViewObserver() {
-            @Override
-            public void startedShowing() {
-                if (mMode == TabListMode.GRID) sIsGridTabSwitcherShowing = true;
-            }
-
-            @Override
-            public void finishedShowing() {}
-
-            @Override
-            public void startedHiding() {
-                if (mMode == TabListMode.GRID) sIsGridTabSwitcherShowing = false;
-            }
-
-            @Override
-            public void finishedHiding() {}
-        });
-
-        if (TabUiFeatureUtilities.isLaunchPolishEnabled()
-                && TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)) {
             mMediator.addTabSwitcherViewObserver(new TabSwitcherViewObserver() {
                 @Override
-                public void startedShowing() {}
-
-                @Override
-                public void finishedShowing() {
-                    if (!mTabModelSelector.isTabStateInitialized()) return;
-
-                    int selectedIndex = mTabModelSelector.getTabModelFilterProvider()
-                                                .getCurrentTabModelFilter()
-                                                .index();
-                    ViewHolder selectedViewHolder =
-                            mTabListCoordinator.getContainerView().findViewHolderForAdapterPosition(
-                                    selectedIndex);
-
-                    if (selectedViewHolder == null) return;
-
-                    View focusView = selectedViewHolder.itemView;
-                    focusView.requestFocus();
-                    focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
+                public void startedShowing() {
+                    if (mMode == TabListMode.GRID) sIsGridTabSwitcherShowing = true;
                 }
 
                 @Override
-                public void startedHiding() {}
+                public void finishedShowing() {}
+
+                @Override
+                public void startedHiding() {
+                    if (mMode == TabListMode.GRID) sIsGridTabSwitcherShowing = false;
+                }
 
                 @Override
                 public void finishedHiding() {}
             });
-        }
 
-        mMessageCardProviderCoordinator = new MessageCardProviderCoordinator(
-                activity, tabModelSelector::isIncognitoSelected, (identifier) -> {
-                    if (identifier == MessageService.MessageType.PRICE_MESSAGE) {
-                        mTabListCoordinator.removeSpecialListItem(
-                                TabProperties.UiType.LARGE_MESSAGE, identifier);
-                    } else {
-                        mTabListCoordinator.removeSpecialListItem(
-                                TabProperties.UiType.MESSAGE, identifier);
-                        appendNextMessage(identifier);
+            if (TabUiFeatureUtilities.isLaunchPolishEnabled()
+                    && TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled(activity)) {
+                mMediator.addTabSwitcherViewObserver(new TabSwitcherViewObserver() {
+                    @Override
+                    public void startedShowing() {}
+
+                    @Override
+                    public void finishedShowing() {
+                        if (!mTabModelSelector.isTabStateInitialized()) return;
+
+                        int selectedIndex = mTabModelSelector.getTabModelFilterProvider()
+                                                    .getCurrentTabModelFilter()
+                                                    .index();
+                        ViewHolder selectedViewHolder =
+                                mTabListCoordinator.getContainerView()
+                                        .findViewHolderForAdapterPosition(selectedIndex);
+
+                        if (selectedViewHolder == null) return;
+
+                        View focusView = selectedViewHolder.itemView;
+                        focusView.requestFocus();
+                        focusView.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
                     }
+
+                    @Override
+                    public void startedHiding() {}
+
+                    @Override
+                    public void finishedHiding() {}
                 });
-
-        if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)) {
-            ScrimCoordinator gridDialogScrimCoordinator =
-                    shouldUseNewScrim() ? createScrimCoordinator() : scrimCoordinator;
-            mTabGridDialogCoordinator = new TabGridDialogCoordinator(activity, tabModelSelector,
-                    tabContentManager, tabCreatorManager, mCoordinatorView, this, mMediator,
-                    this::getTabGridDialogAnimationSourceView, shareDelegateSupplier,
-                    gridDialogScrimCoordinator, rootView);
-            mMediator.setTabGridDialogController(mTabGridDialogCoordinator.getDialogController());
-        } else {
-            mTabGridDialogCoordinator = null;
-        }
-
-        if (mode == TabListCoordinator.TabListMode.GRID) {
-            if (shouldRegisterMessageItemType()) {
-                mTabListCoordinator.registerItemType(TabProperties.UiType.MESSAGE,
-                        new LayoutViewBuilder(R.layout.tab_grid_message_card_item),
-                        MessageCardViewBinder::bind);
             }
 
-            if (TabUiFeatureUtilities.isTabGridLayoutAndroidNewTabTileEnabled()) {
-                mTabListCoordinator.registerItemType(TabProperties.UiType.NEW_TAB_TILE,
-                        new LayoutViewBuilder(R.layout.new_tab_tile_card_item),
-                        NewTabTileViewBinder::bind);
-            }
-
-            if (PriceTrackingFeatures.isPriceTrackingEnabled()) {
-                mTabListCoordinator.registerItemType(TabProperties.UiType.LARGE_MESSAGE,
-                        new LayoutViewBuilder(R.layout.large_message_card_item),
-                        LargeMessageCardViewBinder::bind);
-
-                if (PriceTrackingFeatures.getPriceTrackingEnabled()) {
-                    mPriceAnnotationsPrefObserver = key -> {
-                        if (PriceTrackingUtilities.TRACK_PRICES_ON_TABS.equals(key)
-                                && !mTabModelSelector.isIncognitoSelected()
-                                && mTabModelSelector.isTabStateInitialized()) {
-                            resetWithTabList(mTabModelSelector.getTabModelFilterProvider()
-                                                     .getCurrentTabModelFilter(),
-                                    false, isShowingTabsInMRUOrder(mMode));
+            mMessageCardProviderCoordinator = new MessageCardProviderCoordinator(
+                    activity, tabModelSelector::isIncognitoSelected, (identifier) -> {
+                        if (identifier == MessageService.MessageType.PRICE_MESSAGE) {
+                            mTabListCoordinator.removeSpecialListItem(
+                                    TabProperties.UiType.LARGE_MESSAGE, identifier);
+                        } else {
+                            mTabListCoordinator.removeSpecialListItem(
+                                    TabProperties.UiType.MESSAGE, identifier);
+                            appendNextMessage(identifier);
                         }
-                    };
-                    SharedPreferencesManager.getInstance().addObserver(
-                            mPriceAnnotationsPrefObserver);
+                    });
+
+            if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(activity)) {
+                ScrimCoordinator gridDialogScrimCoordinator =
+                        shouldUseNewScrim() ? createScrimCoordinator() : scrimCoordinator;
+                mTabGridDialogCoordinator = new TabGridDialogCoordinator(activity, tabModelSelector,
+                        tabContentManager, tabCreatorManager, mCoordinatorView, this, mMediator,
+                        this::getTabGridDialogAnimationSourceView, shareDelegateSupplier,
+                        gridDialogScrimCoordinator, rootView);
+                mMediator.setTabGridDialogController(
+                        mTabGridDialogCoordinator.getDialogController());
+            } else {
+                mTabGridDialogCoordinator = null;
+            }
+
+            if (mode == TabListCoordinator.TabListMode.GRID) {
+                if (shouldRegisterMessageItemType()) {
+                    mTabListCoordinator.registerItemType(TabProperties.UiType.MESSAGE,
+                            new LayoutViewBuilder(R.layout.tab_grid_message_card_item),
+                            MessageCardViewBinder::bind);
+                }
+
+                if (TabUiFeatureUtilities.isTabGridLayoutAndroidNewTabTileEnabled()) {
+                    mTabListCoordinator.registerItemType(TabProperties.UiType.NEW_TAB_TILE,
+                            new LayoutViewBuilder(R.layout.new_tab_tile_card_item),
+                            NewTabTileViewBinder::bind);
+                }
+
+                if (PriceTrackingFeatures.isPriceTrackingEnabled()) {
+                    mTabListCoordinator.registerItemType(TabProperties.UiType.LARGE_MESSAGE,
+                            new LayoutViewBuilder(R.layout.large_message_card_item),
+                            LargeMessageCardViewBinder::bind);
+
+                    if (PriceTrackingFeatures.getPriceTrackingEnabled()) {
+                        mPriceAnnotationsPrefObserver = key -> {
+                            if (PriceTrackingUtilities.TRACK_PRICES_ON_TABS.equals(key)
+                                    && !mTabModelSelector.isIncognitoSelected()
+                                    && mTabModelSelector.isTabStateInitialized()) {
+                                resetWithTabList(mTabModelSelector.getTabModelFilterProvider()
+                                                         .getCurrentTabModelFilter(),
+                                        false, isShowingTabsInMRUOrder(mMode));
+                            }
+                        };
+                        SharedPreferencesManager.getInstance().addObserver(
+                                mPriceAnnotationsPrefObserver);
+                    }
                 }
             }
+
+            if (CachedFeatureFlags.isEnabled(ChromeFeatureList.INSTANT_START)
+                    || TabUiFeatureUtilities.ENABLE_SEARCH_CHIP.getValue()
+                            && mode != TabListCoordinator.TabListMode.CAROUSEL) {
+                mTabAttributeCache = new TabAttributeCache(mTabModelSelector);
+            }
+
+            mMenuOrKeyboardActionController = menuOrKeyboardActionController;
+            mMenuOrKeyboardActionController.registerMenuOrKeyboardActionHandler(
+                    mTabSwitcherMenuActionHandler);
+
+            mLifecycleDispatcher = lifecycleDispatcher;
+            mLifecycleDispatcher.register(this);
         }
-
-        if (CachedFeatureFlags.isEnabled(ChromeFeatureList.INSTANT_START)
-                || TabUiFeatureUtilities.ENABLE_SEARCH_CHIP.getValue()
-                        && mode != TabListCoordinator.TabListMode.CAROUSEL) {
-            mTabAttributeCache = new TabAttributeCache(mTabModelSelector);
-        }
-
-        mMenuOrKeyboardActionController = menuOrKeyboardActionController;
-        mMenuOrKeyboardActionController.registerMenuOrKeyboardActionHandler(
-                mTabSwitcherMenuActionHandler);
-
-        mLifecycleDispatcher = lifecycleDispatcher;
-        mLifecycleDispatcher.register(this);
     }
 
     /**
@@ -379,68 +386,75 @@
     @Override
     public void initWithNative() {
         if (mIsInitialized) return;
+        try (TraceEvent e = TraceEvent.scoped("TabSwitcherCoordintor.initWithNative")) {
+            setUpTabGroupManualSelectionMode(mActivity, mTabContentManager, mSnackbarManager);
 
-        setUpTabGroupManualSelectionMode(mActivity, mTabContentManager, mSnackbarManager);
+            mTabListCoordinator.initWithNative(mDynamicResourceLoaderSupplier.get());
+            if (mTabGridDialogCoordinator != null) {
+                mTabGridDialogCoordinator.initWithNative(mActivity, mTabModelSelector,
+                        mTabContentManager, mTabListCoordinator.getTabGroupTitleEditor());
+            }
 
-        mTabListCoordinator.initWithNative(mDynamicResourceLoaderSupplier.get());
-        if (mTabGridDialogCoordinator != null) {
-            mTabGridDialogCoordinator.initWithNative(mActivity, mTabModelSelector,
-                    mTabContentManager, mTabListCoordinator.getTabGroupTitleEditor());
+            mMultiThumbnailCardProvider.initWithNative();
+
+            if (mMode == TabListCoordinator.TabListMode.GRID) {
+                if (CachedFeatureFlags.isEnabled(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS)) {
+                    mTabSuggestionsOrchestrator = new TabSuggestionsOrchestrator(
+                            mActivity, mTabModelSelector, mLifecycleDispatcher);
+                    TabSuggestionMessageService tabSuggestionMessageService =
+                            new TabSuggestionMessageService(mActivity, mTabModelSelector,
+                                    mTabSelectionEditorCoordinator.getController());
+                    mTabSuggestionsOrchestrator.addObserver(tabSuggestionMessageService);
+                    mMessageCardProviderCoordinator.subscribeMessageService(
+                            tabSuggestionMessageService);
+                }
+
+                if (TabUiFeatureUtilities.isTabGridLayoutAndroidNewTabTileEnabled()) {
+                    mNewTabTileCoordinator =
+                            new NewTabTileCoordinator(mTabModelSelector, mTabCreatorManager);
+                }
+
+                if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mActivity)
+                        && !TabSwitcherCoordinator.isShowingTabsInMRUOrder(mMode)) {
+                    mTabGridIphDialogCoordinator = new TabGridIphDialogCoordinator(
+                            mActivity, mContainer, mModalDialogManager);
+                    IphMessageService iphMessageService =
+                            new IphMessageService(mTabGridIphDialogCoordinator);
+                    mMessageCardProviderCoordinator.subscribeMessageService(iphMessageService);
+                }
+            }
+
+            // TODO(crbug.com/1222762): Only call setUpPriceTracking in GRID TabSwitcher.
+            setUpPriceTracking(mActivity, mModalDialogManager);
+
+            mIsInitialized = true;
         }
-
-        mMultiThumbnailCardProvider.initWithNative();
-
-        if (mMode == TabListCoordinator.TabListMode.GRID) {
-            if (CachedFeatureFlags.isEnabled(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS)) {
-                mTabSuggestionsOrchestrator = new TabSuggestionsOrchestrator(
-                        mActivity, mTabModelSelector, mLifecycleDispatcher);
-                TabSuggestionMessageService tabSuggestionMessageService =
-                        new TabSuggestionMessageService(mActivity, mTabModelSelector,
-                                mTabSelectionEditorCoordinator.getController());
-                mTabSuggestionsOrchestrator.addObserver(tabSuggestionMessageService);
-                mMessageCardProviderCoordinator.subscribeMessageService(
-                        tabSuggestionMessageService);
-            }
-
-            if (TabUiFeatureUtilities.isTabGridLayoutAndroidNewTabTileEnabled()) {
-                mNewTabTileCoordinator =
-                        new NewTabTileCoordinator(mTabModelSelector, mTabCreatorManager);
-            }
-
-            if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled(mActivity)
-                    && !TabSwitcherCoordinator.isShowingTabsInMRUOrder(mMode)) {
-                mTabGridIphDialogCoordinator =
-                        new TabGridIphDialogCoordinator(mActivity, mContainer, mModalDialogManager);
-                IphMessageService iphMessageService =
-                        new IphMessageService(mTabGridIphDialogCoordinator);
-                mMessageCardProviderCoordinator.subscribeMessageService(iphMessageService);
-            }
-        }
-
-        // TODO(crbug.com/1222762): Only call setUpPriceTracking in GRID TabSwitcher.
-        setUpPriceTracking(mActivity, mModalDialogManager);
-
-        mIsInitialized = true;
     }
 
     private void setUpTabGroupManualSelectionMode(
             Context context, TabContentManager tabContentManager, SnackbarManager snackbarManager) {
-        // For tab switcher in carousel mode, the selection editor should still follow grid style.
-        int selectionEditorMode = mMode == TabListCoordinator.TabListMode.CAROUSEL
-                ? TabListCoordinator.TabListMode.GRID
-                : mMode;
-        mTabSelectionEditorCoordinator =
-                new TabSelectionEditorCoordinator(context, mCoordinatorView, mTabModelSelector,
-                        tabContentManager, selectionEditorMode, mRootView);
-        mMediator.initWithNative(mTabSelectionEditorCoordinator.getController(), snackbarManager);
+        try (TraceEvent e = TraceEvent.scoped(
+                     "TabSwitcherCoordintor.setUpTabGroupManualSelectionMode")) {
+            // For tab switcher in carousel mode, the selection editor should still follow grid
+            // style.
+            int selectionEditorMode = mMode == TabListCoordinator.TabListMode.CAROUSEL
+                    ? TabListCoordinator.TabListMode.GRID
+                    : mMode;
+            mTabSelectionEditorCoordinator =
+                    new TabSelectionEditorCoordinator(context, mCoordinatorView, mTabModelSelector,
+                            tabContentManager, selectionEditorMode, mRootView);
+            mMediator.initWithNative(
+                    mTabSelectionEditorCoordinator.getController(), snackbarManager);
 
-        mTabGroupManualSelectionMode = new TabGroupManualSelectionMode(
-                context.getString(R.string.tab_selection_editor_group),
-                R.plurals.accessibility_tab_selection_editor_group_button, 2,
-                new TabSelectionEditorActionProvider(mTabSelectionEditorCoordinator.getController(),
-                        TabSelectionEditorActionProvider.TabSelectionEditorAction.GROUP),
-                new TabSelectionEditorNavigationProvider(
-                        mTabSelectionEditorCoordinator.getController()));
+            mTabGroupManualSelectionMode = new TabGroupManualSelectionMode(
+                    context.getString(R.string.tab_selection_editor_group),
+                    R.plurals.accessibility_tab_selection_editor_group_button, 2,
+                    new TabSelectionEditorActionProvider(
+                            mTabSelectionEditorCoordinator.getController(),
+                            TabSelectionEditorActionProvider.TabSelectionEditorAction.GROUP),
+                    new TabSelectionEditorNavigationProvider(
+                            mTabSelectionEditorCoordinator.getController()));
+        }
     }
 
     private void setUpPriceTracking(Context context, ModalDialogManager modalDialogManager) {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
index 62cd832..bcf4547 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogTest.java
@@ -780,7 +780,6 @@
 
     @Test
     @MediumTest
-    @DisabledTest(message = "crbug.com/1157518")
     public void testAdjustBackGroundViewAccessibilityImportance() {
         final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         createTabs(cta, false, 2);
diff --git a/chrome/android/java/res/drawable/ic_incognito_reauth_promo_icon.xml b/chrome/android/java/res/drawable/ic_incognito_reauth_promo_icon.xml
new file mode 100644
index 0000000..7b801df6
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_incognito_reauth_promo_icon.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+    <!-- 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. -->
+
+<!--TODO(crbug.com/1227656): Remove UnusedResource warning when in production -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:ignore="UnusedResources"
+    android:width="52dp"
+    android:height="52dp"
+    android:viewportWidth="52"
+    android:viewportHeight="52">
+  <path
+      android:pathData="M21,26m21,0a21,21 0,1 0,-42 0a21,21 0,1 0,42 0"
+      android:fillColor="@color/baseline_neutral_variant_500"/>
+  <path
+      android:pathData="M43,26C40.817,26 39,27.828 39,30.143V36H47V30.143C47,27.828 45.183,26 43,26Z"
+      android:strokeWidth="2"
+      android:fillColor="#00000000"
+      android:strokeColor="@color/baseline_primary_200"/>
+  <path
+      android:pathData="M50,33C51.105,33 52,33.895 52,35V45C52,46.105 51.105,47 50,47H36C34.895,47 34,46.105 34,45V35C34,33.895 34.895,33 36,33H50ZM43,42C41.895,42 41,41.105 41,40C41,38.895 41.895,38 43,38C44.105,38 45,38.895 45,40C45,41.105 44.105,42 43,42Z"
+      android:fillColor="@color/baseline_primary_200"
+      android:fillType="evenOdd"/>
+  <path
+      android:pathData="M8.25,24.584H33.75V26.001H8.25V24.584Z"
+      android:fillColor="@color/baseline_neutral_900_with_neutral_200_alpha_5_with_primary_200_alpha_2"/>
+  <path
+      android:pathData="M13.038,23.167L16.282,14.526C16.552,13.817 17.331,13.435 18.053,13.676L21,14.667L23.961,13.676C24.683,13.435 25.462,13.817 25.732,14.526L28.962,23.167H13.038Z"
+      android:fillColor="@color/baseline_neutral_900_with_neutral_200_alpha_5_with_primary_200_alpha_2"/>
+  <path
+      android:pathData="M14.625,27.417C16.977,27.417 18.932,29.061 19.442,31.256C20.632,30.746 21.737,30.888 22.558,31.242C23.083,29.046 25.038,27.417 27.375,27.417C30.109,27.417 32.333,29.641 32.333,32.376C32.333,35.11 30.109,37.334 27.375,37.334C24.768,37.334 22.657,35.322 22.459,32.772C22.034,32.475 20.915,31.922 19.541,32.801C19.314,35.336 17.218,37.334 14.625,37.334C11.891,37.334 9.667,35.11 9.667,32.376C9.667,29.641 11.891,27.417 14.625,27.417ZM27.375,35.917C29.33,35.917 30.917,34.331 30.917,32.376C30.917,30.421 29.33,28.834 27.375,28.834C25.42,28.834 23.833,30.421 23.833,32.376C23.833,34.331 25.42,35.917 27.375,35.917ZM14.625,35.917C16.58,35.917 18.167,34.331 18.167,32.376C18.167,30.421 16.58,28.834 14.625,28.834C12.67,28.834 11.083,30.421 11.083,32.376C11.083,34.331 12.67,35.917 14.625,35.917Z"
+      android:fillColor="@color/baseline_neutral_900_with_neutral_200_alpha_5_with_primary_200_alpha_2"/>
+</vector>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
index 5e24942..9670f5b1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AppHooks.java
@@ -29,7 +29,7 @@
 import org.chromium.chrome.browser.notifications.chime.ChimeDelegate;
 import org.chromium.chrome.browser.omaha.RequestGenerator;
 import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmark;
-import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksDelegateImpl;
+import org.chromium.chrome.browser.partnerbookmarks.PartnerBookmarksProviderIterator;
 import org.chromium.chrome.browser.password_manager.GooglePasswordManagerUIProvider;
 import org.chromium.chrome.browser.policy.PolicyAuditor;
 import org.chromium.chrome.browser.rlz.RevenueStats;
@@ -244,7 +244,7 @@
      */
     @Nullable
     public PartnerBookmark.BookmarkIterator getPartnerBookmarkIterator() {
-        return new PartnerBookmarksDelegateImpl().createIterator();
+        return PartnerBookmarksProviderIterator.createIfAvailable();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/download/home/DownloadManagerCoordinatorFactoryHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/app/download/home/DownloadManagerCoordinatorFactoryHelper.java
index 370557a..83b6b514 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/download/home/DownloadManagerCoordinatorFactoryHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/download/home/DownloadManagerCoordinatorFactoryHelper.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool;
-import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
 /** A helper class to build and return an {@link DownloadManagerCoordinator}. */
@@ -44,9 +43,8 @@
                 DownloadManagerCoordinatorFactoryHelper::settingsLaunchHelper;
         return DownloadManagerCoordinatorFactory.create(activity, config,
                 new PrefetchEnabledSupplier(), settingsLaunchHelper, snackbarManager,
-                modalDialogManager, UserPrefs.get(profile),
-                TrackerFactory.getTrackerForProfile(profile), new FaviconProviderImpl(profile),
-                OfflineContentAggregatorFactory.get(),
+                modalDialogManager, TrackerFactory.getTrackerForProfile(profile),
+                new FaviconProviderImpl(profile), OfflineContentAggregatorFactory.get(),
                 GlobalDiscardableReferencePool.getReferencePool());
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index eac84e1..03fd1ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -57,8 +57,6 @@
 import org.chromium.components.offline_items_collection.ContentId;
 import org.chromium.components.offline_items_collection.FailState;
 import org.chromium.components.offline_items_collection.LegacyHelpers;
-import org.chromium.components.offline_items_collection.OfflineItem;
-import org.chromium.components.offline_items_collection.OfflineItemSchedule;
 import org.chromium.components.offline_items_collection.PendingState;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
@@ -1304,22 +1302,6 @@
     }
 
     /**
-     * Change the download schedule to start the download in a different condition.
-     * @param id The id of the {@link OfflineItem} that requests the change.
-     * @param schedule The download schedule that defines when to start the download.
-     * @param otrProfileID The {@link OTRProfileID} of the download. Null if in regular mode.
-     */
-    // Deprecated after new download backend.
-    public void changeSchedule(
-            final ContentId id, final OfflineItemSchedule schedule, OTRProfileID otrProfileID) {
-        boolean onlyOnWifi = (schedule == null) ? false : schedule.onlyOnWifi;
-        long startTimeMs = (schedule == null) ? -1 : schedule.startTimeMs;
-        DownloadManagerServiceJni.get().changeSchedule(getNativeDownloadManagerService(),
-                DownloadManagerService.this, id.id, onlyOnWifi, startTimeMs,
-                IncognitoUtils.getProfileKeyFromOTRProfileID(otrProfileID));
-    }
-
-    /**
      * Add an Intent extra for StateAtCancel UMA to know the state of a request prior to a
      * user-initiated cancel.
      * @param intent The Intent associated with the download action.
@@ -1726,8 +1708,6 @@
         void renameDownload(long nativeDownloadManagerService, DownloadManagerService caller,
                 String downloadGuid, String targetName, Callback</*RenameResult*/ Integer> callback,
                 ProfileKey profileKey);
-        void changeSchedule(long nativeDownloadManagerService, DownloadManagerService caller,
-                String downloadGuid, boolean onlyOnWifi, long startTimeMs, ProfileKey profileKey);
         void getAllDownloads(long nativeDownloadManagerService, DownloadManagerService caller,
                 ProfileKey profileKey);
         void checkForExternallyRemovedDownloads(long nativeDownloadManagerService,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/COMMON_METADATA b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/COMMON_METADATA
new file mode 100644
index 0000000..087172e2
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/COMMON_METADATA
@@ -0,0 +1,3 @@
+monorail {
+  component: "UI>Browser>Bookmarks"
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA
index 424fe1a..b38f8e2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA
@@ -1 +1 @@
-mixins: "//chrome/browser/partnerbookmarks/COMMON_METADATA"
+mixins: "//chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/COMMON_METADATA"
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java
similarity index 100%
rename from chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java
rename to chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java
similarity index 100%
rename from chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java
rename to chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
similarity index 93%
rename from chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
rename to chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
index 16fc14e1e..ffe33d6a 100644
--- a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java
@@ -17,7 +17,7 @@
 /**
  * Imports bookmarks from partner content provider using the private provider API.
  */
-public class PartnerBookmarksProviderIterator implements PartnerBookmarkIterator {
+public class PartnerBookmarksProviderIterator implements PartnerBookmark.BookmarkIterator {
     private static final String TAG = "PartnerBookmarks";
     private static final String PROVIDER_AUTHORITY = "com.android.partnerbookmarks";
     private static final Uri CONTENT_URI = new Uri.Builder()
@@ -45,15 +45,9 @@
     private static final String BOOKMARKS_SORT_ORDER =
             BOOKMARKS_COLUMN_TYPE + " DESC, " + BOOKMARKS_COLUMN_ID + " ASC";
 
-    private static final String[] BOOKMARKS_PROJECTION = {
-            BOOKMARKS_COLUMN_ID,
-            BOOKMARKS_COLUMN_URL,
-            BOOKMARKS_COLUMN_TITLE,
-            BOOKMARKS_COLUMN_TYPE,
-            BOOKMARKS_COLUMN_PARENT,
-            BOOKMARKS_COLUMN_FAVICON,
-            BOOKMARKS_COLUMN_TOUCHICON,
-    };
+    private static final String[] BOOKMARKS_PROJECTION = {BOOKMARKS_COLUMN_ID, BOOKMARKS_COLUMN_URL,
+            BOOKMARKS_COLUMN_TITLE, BOOKMARKS_COLUMN_TYPE, BOOKMARKS_COLUMN_PARENT,
+            BOOKMARKS_COLUMN_FAVICON, BOOKMARKS_COLUMN_TOUCHICON};
 
     private final Cursor mCursor;
 
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
similarity index 94%
rename from chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
rename to chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
index ba304ec..123d9f65ac 100644
--- a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java
@@ -6,14 +6,12 @@
 
 import android.content.Context;
 
-import androidx.annotation.GuardedBy;
-
 import org.chromium.base.Log;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.supplier.Supplier;
 import org.chromium.base.task.AsyncTask;
+import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.ui.base.ViewUtils;
 
@@ -21,6 +19,8 @@
 import java.util.LinkedHashMap;
 import java.util.Set;
 
+import javax.annotation.concurrent.GuardedBy;
+
 /**
  * Reads bookmarks from the partner content provider (if any).
  */
@@ -38,9 +38,6 @@
     /** ID used to indicate an invalid bookmark node. */
     static final long INVALID_BOOKMARK_ID = -1;
 
-    /** Injected dependency. */
-    private final Supplier<PartnerBookmark.BookmarkIterator> mBookmarkIteratorSupplier;
-
     /** Storage for failed favicon retrieval attempts to throttle future requests. **/
     private PartnerBookmarksFaviconThrottle mFaviconThrottle;
 
@@ -96,14 +93,10 @@
      * Creates the instance of the reader.
      * @param context A Context object.
      * @param browserCustomizations Provides status of partner customizations.
-     * @param bookmarkIteratorSupplier Source of the {@link PartnerBookmarkIterator}. This argument
-     *         should be removed once {@link PartnerBookmarksDelegate} can be used instead.
      */
-    public PartnerBookmarksReader(Context context,
-            PartnerBrowserCustomizations browserCustomizations,
-            Supplier<PartnerBookmark.BookmarkIterator> bookmarkIteratorSupplier) {
+    public PartnerBookmarksReader(
+            Context context, PartnerBrowserCustomizations browserCustomizations) {
         mContext = context;
-        mBookmarkIteratorSupplier = bookmarkIteratorSupplier;
         mNativePartnerBookmarksReader =
                 PartnerBookmarksReaderJni.get().init(PartnerBookmarksReader.this);
         if (!browserCustomizations.isInitialized()) {
@@ -260,7 +253,8 @@
                 // background thread as well.
                 mFaviconThrottle = new PartnerBookmarksFaviconThrottle();
             }
-            PartnerBookmark.BookmarkIterator bookmarkIterator = mBookmarkIteratorSupplier.get();
+            PartnerBookmark.BookmarkIterator bookmarkIterator =
+                    AppHooks.get().getPartnerBookmarkIterator();
             if (bookmarkIterator == null) return null;
 
             // Get a snapshot of the bookmarks.
@@ -283,7 +277,7 @@
                 // Check for duplicate URLs.
                 if (!bookmark.mIsFolder && urlSet.contains(bookmark.mUrl)) {
                     Log.i(TAG,
-                            "More than one bookmark pointing to " + bookmark.mUrl + " "
+                            "More than one bookmark pointing to " + bookmark.mUrl + ". "
                                     + "Keeping only the first one for consistency with Chromium.");
                     continue;
                 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
index 34b1cd3..04b1200 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksShim.java
@@ -7,7 +7,6 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 
-import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.components.version_info.VersionInfo;
 
@@ -33,8 +32,7 @@
         sIsReadingAttempted = true;
 
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(context, PartnerBrowserCustomizations.getInstance(),
-                        AppHooks.get()::getPartnerBookmarkIterator);
+                new PartnerBookmarksReader(context, PartnerBrowserCustomizations.getInstance());
 
         boolean systemOrPreStable =
                 (context.getApplicationInfo().flags & ApplicationInfo.FLAG_SYSTEM) == 1
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
index d23f73a..daf1d376 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.NightModeTestUtils;
@@ -56,6 +57,7 @@
 @RunWith(ParameterizedRunner.class)
 @ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@DisableFeatures({ChromeFeatureList.FEED_POSITION_ANDROID})
 public class ExploreSitesPageTest {
     // clang-format on
 
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA
new file mode 100644
index 0000000..b38f8e2
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/DIR_METADATA
@@ -0,0 +1 @@
+mixins: "//chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/COMMON_METADATA"
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/OWNERS b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/OWNERS
new file mode 100644
index 0000000..77d93dd
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/OWNERS
@@ -0,0 +1 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/partnerbookmarks/OWNERS
diff --git a/chrome/browser/partnerbookmarks/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java
similarity index 100%
rename from chrome/browser/partnerbookmarks/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java
diff --git a/chrome/browser/partnerbookmarks/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
similarity index 96%
rename from chrome/browser/partnerbookmarks/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
rename to chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
index 402082a5..84f6226 100644
--- a/chrome/browser/partnerbookmarks/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java
@@ -57,7 +57,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
 
         Mockito.verify(mBrowserCustomizations, Mockito.never()).initializeAsync(mContextMock);
 
@@ -72,7 +72,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
 
         Mockito.verify(mBrowserCustomizations).initializeAsync(mContextMock);
 
@@ -87,7 +87,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
 
         Mockito.verify(mBrowserCustomizations, Mockito.never()).initializeAsync(mContextMock);
 
@@ -102,7 +102,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
 
         Mockito.verify(mBrowserCustomizations).initializeAsync(mContextMock);
 
@@ -117,7 +117,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
         reader.onBookmarksRead();
 
         Mockito.verify(mJniMock, Mockito.never())
@@ -130,7 +130,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
         Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false);
         mBrowserCustomizationsInitCallback.getValue().run();
 
@@ -144,7 +144,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
         Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false);
         mBrowserCustomizationsInitCallback.getValue().run();
         reader.onBookmarksRead();
@@ -159,7 +159,7 @@
 
         @SuppressWarnings("unused")
         PartnerBookmarksReader reader =
-                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations, null);
+                new PartnerBookmarksReader(mContextMock, mBrowserCustomizations);
         Mockito.when(mBrowserCustomizations.isBookmarksEditingDisabled()).thenReturn(false);
         reader.onBookmarksRead();
         mBrowserCustomizationsInitCallback.getValue().run();
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index b4aa4b5..dcf5787 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3286,7 +3286,6 @@
       "//chrome/browser/notifications/chime/android",
       "//chrome/browser/notifications/scheduler/public",
       "//chrome/browser/optimization_guide/android:jni_headers",
-      "//chrome/browser/partnerbookmarks:jni_headers",
       "//chrome/browser/partnercustomizations:jni_headers",
       "//chrome/browser/password_check/android:jni_headers",
       "//chrome/browser/password_check/android:password_check_enums_srcjar",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 34be555..d563b4e8 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3415,7 +3415,7 @@
      SINGLE_VALUE_TYPE(switches::kEnableUnifiedDesktop)},
     {"rounded-display", flag_descriptions::kRoundedDisplay,
      flag_descriptions::kRoundedDisplayDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(ash::features::kRoundedDisplay)},
+     FEATURE_VALUE_TYPE(display::features::kRoundedDisplay)},
     {"bluetooth-fix-a2dp-packet-size",
      flag_descriptions::kBluetoothFixA2dpPacketSizeName,
      flag_descriptions::kBluetoothFixA2dpPacketSizeDescription, kOsCrOS,
@@ -8794,13 +8794,6 @@
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  // In order to be considered for Lacros, flags additionally need to be usable
-  // on Chrome OS.
-  if (!(entry.supported_platforms & (kOsCrOS | kOsCrOSOwnerOnly)))
-    return true;
-#endif  //  BUILDFLAG(IS_CHROMEOS_LACROS)
-
   // enable-unsafe-webgpu is only available on Dev/Canary channels.
   if (!strcmp("enable-unsafe-webgpu", entry.internal_name) &&
       channel != version_info::Channel::DEV &&
diff --git a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
index 4ca2e85a..20c6721c 100644
--- a/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
+++ b/chrome/browser/android/bookmarks/partner_bookmarks_reader.cc
@@ -12,11 +12,11 @@
 #include "base/guid.h"
 #include "base/logging.h"
 #include "base/synchronization/waitable_event.h"
+#include "chrome/android/chrome_jni_headers/PartnerBookmarksReader_jni.h"
 #include "chrome/browser/android/bookmarks/partner_bookmarks_shim.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/favicon/favicon_service_factory.h"
 #include "chrome/browser/favicon/large_icon_service_factory.h"
-#include "chrome/browser/partnerbookmarks/jni_headers/PartnerBookmarksReader_jni.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "components/favicon/core/favicon_service.h"
diff --git a/chrome/browser/apps/app_service/app_launch_params.cc b/chrome/browser/apps/app_service/app_launch_params.cc
index dd5139b2..d87f831a 100644
--- a/chrome/browser/apps/app_service/app_launch_params.cc
+++ b/chrome/browser/apps/app_service/app_launch_params.cc
@@ -26,7 +26,7 @@
                                  apps::mojom::LaunchSource launch_source,
                                  int64_t display_id,
                                  const std::vector<base::FilePath>& files,
-                                 const apps::mojom::IntentPtr& intentPtr)
+                                 const IntentPtr& intentPtr)
     : app_id(app_id),
       container(container),
       disposition(disposition),
@@ -34,7 +34,7 @@
       launch_source(launch_source),
       display_id(display_id),
       launch_files(files),
-      intent(intentPtr ? intentPtr.Clone() : nullptr) {}
+      intent(intentPtr ? intentPtr->Clone() : nullptr) {}
 
 AppLaunchParams::AppLaunchParams(AppLaunchParams&&) = default;
 AppLaunchParams& AppLaunchParams::operator=(AppLaunchParams&&) = default;
diff --git a/chrome/browser/apps/app_service/app_launch_params.h b/chrome/browser/apps/app_service/app_launch_params.h
index 636b80e1..0799a5a 100644
--- a/chrome/browser/apps/app_service/app_launch_params.h
+++ b/chrome/browser/apps/app_service/app_launch_params.h
@@ -10,6 +10,7 @@
 
 #include "base/command_line.h"
 #include "base/files/file_path.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/window_open_disposition.h"
@@ -32,7 +33,7 @@
                   apps::mojom::LaunchSource launch_source,
                   int64_t display_id,
                   const std::vector<base::FilePath>& files,
-                  const apps::mojom::IntentPtr& intentPtr);
+                  const IntentPtr& intentPtr);
 
   AppLaunchParams(const AppLaunchParams&) = delete;
   AppLaunchParams& operator=(const AppLaunchParams&) = delete;
@@ -90,7 +91,7 @@
 
   // The intent the application was launched with. Empty if the application was
   // not launched with intent.
-  apps::mojom::IntentPtr intent;
+  IntentPtr intent;
 
   // When PWA is launched as a URL handler, the URL that we should launch the
   // PWA to. Null when it's not a URL handler launch.
diff --git a/chrome/browser/apps/app_service/browser_app_launcher.cc b/chrome/browser/apps/app_service/browser_app_launcher.cc
index f2b7d13..8ef3ea7 100644
--- a/chrome/browser/apps/app_service/browser_app_launcher.cc
+++ b/chrome/browser/apps/app_service/browser_app_launcher.cc
@@ -27,6 +27,7 @@
 #include "components/app_restore/full_restore_save_handler.h"
 #include "components/app_restore/full_restore_utils.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/sessions/core/session_id.h"
 #endif
 
diff --git a/chrome/browser/apps/app_service/launch_utils.cc b/chrome/browser/apps/app_service/launch_utils.cc
index fb9a73e5..a326bdc 100644
--- a/chrome/browser/apps/app_service/launch_utils.cc
+++ b/chrome/browser/apps/app_service/launch_utils.cc
@@ -24,6 +24,7 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/webui_url_constants.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/sessions/core/session_id.h"
 #include "extensions/browser/extension_registry.h"
@@ -249,7 +250,7 @@
   }
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-  params.intent = std::move(intent);
+  params.intent = ConvertMojomIntentToIntent(intent);
 
   return params;
 }
@@ -439,7 +440,7 @@
     }
   }
 
-  params.intent = apps_util::ConvertCrosapiToAppServiceIntent(
+  params.intent = apps_util::CreateAppServiceIntentFromCrosapi(
       crosapi_params->intent, profile);
   return params;
 }
diff --git a/chrome/browser/apps/app_service/launch_utils_unittest.cc b/chrome/browser/apps/app_service/launch_utils_unittest.cc
index 16d5b37b..dc4a9af6 100644
--- a/chrome/browser/apps/app_service/launch_utils_unittest.cc
+++ b/chrome/browser/apps/app_service/launch_utils_unittest.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -268,7 +269,8 @@
   auto disposition = WindowOpenDisposition::NEW_WINDOW;
   const int64_t kDisplayId = 4;
   auto params = CreateLaunchParams(container, disposition, false, kDisplayId);
-  params.intent = apps_util::CreateIntentFromUrl(GURL("abc.example.com"));
+  params.intent = std::make_unique<apps::Intent>(apps_util::kIntentActionView,
+                                                 GURL("abc.example.com"));
 
   auto crosapi_params = apps::ConvertLaunchParamsToCrosapi(params, &profile_);
   auto converted_params =
@@ -278,7 +280,7 @@
   EXPECT_EQ(params.disposition, converted_params.disposition);
   EXPECT_EQ(params.launch_source, converted_params.launch_source);
   EXPECT_EQ(params.display_id, converted_params.display_id);
-  EXPECT_EQ(params.intent, converted_params.intent);
+  EXPECT_EQ(*params.intent, *converted_params.intent);
 }
 
 // Verifies that convert params from crosapi with incomplete params works.
@@ -344,10 +346,10 @@
   EXPECT_EQ(converted_params.intent->action, apps_util::kIntentActionSend);
   EXPECT_EQ(converted_params.intent->mime_type, kIntentMimeType);
   EXPECT_EQ(converted_params.intent->share_text, kShareText);
-  EXPECT_EQ(converted_params.intent->files->size(), 1U);
-  EXPECT_EQ((*converted_params.intent->files)[0]->file_name,
+  EXPECT_EQ(converted_params.intent->files.size(), 1U);
+  EXPECT_EQ(converted_params.intent->files[0]->file_name,
             base::SafeBaseName::Create(kBaseName));
-  EXPECT_EQ((*converted_params.intent->files)[0]->mime_type, kFileMimeType);
+  EXPECT_EQ(converted_params.intent->files[0]->mime_type, kFileMimeType);
 }
 #endif  // BUILDFLAG(IS_CHROMEOS_LACROS)
 
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc
index c9675ad..79252db 100644
--- a/chrome/browser/apps/app_service/publishers/arc_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -51,6 +51,7 @@
 #include "components/arc/common/intent_helper/arc_intent_helper_package.h"
 #include "components/services/app_service/public/cpp/app_types.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
@@ -464,7 +465,8 @@
   ::full_restore::SaveAppLaunchInfo(
       file_path,
       std::make_unique<app_restore::AppLaunchInfo>(
-          app_id, event_flags, std::move(intent), session_id, display_id));
+          app_id, event_flags, apps::ConvertMojomIntentToIntent(intent),
+          session_id, display_id));
 
   std::move(callback).Run(/*success=*/true);
 }
@@ -706,9 +708,9 @@
                                          /*prefer_container=*/false);
   auto window_info = apps::MakeWindowInfo(params.display_id);
   if (params.intent) {
-    LaunchAppWithIntent(params.app_id, event_flags, std::move(params.intent),
-                        params.launch_source, std::move(window_info),
-                        base::DoNothing());
+    LaunchAppWithIntent(
+        params.app_id, event_flags, ConvertIntentToMojomIntent(params.intent),
+        params.launch_source, std::move(window_info), base::DoNothing());
   } else {
     Launch(params.app_id, event_flags, params.launch_source,
            std::move(window_info));
@@ -904,8 +906,9 @@
     full_restore::SaveAppLaunchInfo(
         profile_->GetPath(),
         std::make_unique<app_restore::AppLaunchInfo>(
-            app_id, event_flags, std::move(intent_for_full_restore), session_id,
-            display_id));
+            app_id, event_flags,
+            apps::ConvertMojomIntentToIntent(intent_for_full_restore),
+            session_id, display_id));
     std::move(callback).Run(/*success=*/true);
     return;
   }
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.cc b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
index ca5a1a5..92786cc 100644
--- a/chrome/browser/apps/app_service/publishers/crostini_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
@@ -26,6 +26,7 @@
 #include "chrome/grit/generated_resources.h"
 #include "components/prefs/pref_service.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "ui/display/display.h"
@@ -114,9 +115,9 @@
                                          /*prefer_container=*/false);
   auto window_info = apps::MakeWindowInfo(params.display_id);
   if (params.intent) {
-    LaunchAppWithIntent(params.app_id, event_flags, std::move(params.intent),
-                        params.launch_source, std::move(window_info),
-                        base::DoNothing());
+    LaunchAppWithIntent(
+        params.app_id, event_flags, ConvertIntentToMojomIntent(params.intent),
+        params.launch_source, std::move(window_info), base::DoNothing());
   } else {
     Launch(params.app_id, event_flags, params.launch_source,
            std::move(window_info));
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
index f4a7e6e..abde82b 100644
--- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
+++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
@@ -68,6 +68,7 @@
 #include "components/app_restore/full_restore_utils.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/services/app_service/public/cpp/instance.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_filter_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
@@ -204,9 +205,9 @@
     auto event_flags = apps::GetEventFlags(params.container, params.disposition,
                                            /*prefer_container=*/false);
     auto window_info = apps::MakeWindowInfo(params.display_id);
-    LaunchExtension(params.app_id, event_flags, std::move(params.intent),
-                    params.launch_source, std::move(window_info),
-                    base::DoNothing());
+    LaunchExtension(
+        params.app_id, event_flags, ConvertIntentToMojomIntent(params.intent),
+        params.launch_source, std::move(window_info), base::DoNothing());
   }
 }
 
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc
index 5ca21f27..19e1029 100644
--- a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc
+++ b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc
@@ -25,6 +25,7 @@
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/features.h"
 #include "components/app_restore/full_restore_utils.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 
 namespace apps {
@@ -221,7 +222,8 @@
     auto launch_info = std::make_unique<app_restore::AppLaunchInfo>(
         app_id, apps::mojom::LaunchContainer::kLaunchContainerNone,
         WindowOpenDisposition::UNKNOWN, display::kInvalidDisplayId,
-        std::vector<base::FilePath>{}, std::move(intent));
+        std::vector<base::FilePath>{},
+        apps::ConvertMojomIntentToIntent(intent));
     full_restore::SaveAppLaunchInfo(proxy()->profile()->GetPath(),
                                     std::move(launch_info));
   }
diff --git a/chrome/browser/ash/app_restore/app_launch_handler.cc b/chrome/browser/ash/app_restore/app_launch_handler.cc
index 587829d..95d7913 100644
--- a/chrome/browser/ash/app_restore/app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/app_launch_handler.cc
@@ -18,6 +18,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "components/app_constants/constants.h"
 #include "components/app_restore/full_restore_read_handler.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/common/extension.h"
@@ -244,7 +245,7 @@
         !it.second->display_id.has_value()) {
       continue;
     }
-    apps::mojom::IntentPtr intent;
+
     apps::AppLaunchParams params(
         app_id,
         static_cast<apps::mojom::LaunchContainer>(it.second->container.value()),
@@ -253,7 +254,9 @@
         it.second->display_id.value(),
         it.second->file_paths.has_value() ? it.second->file_paths.value()
                                           : std::vector<base::FilePath>{},
-        it.second->intent.has_value() ? it.second->intent.value() : intent);
+        it.second->intent.has_value()
+            ? apps::ConvertMojomIntentToIntent(it.second->intent.value())
+            : nullptr);
     params.restore_id = it.first;
     proxy->LaunchAppWithParams(std::move(params));
   }
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
index ce3275e..100f04e 100644
--- a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
+++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -45,6 +45,7 @@
 #include "components/app_restore/window_properties.h"
 #include "components/exo/wm_helper.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "ui/display/display.h"
@@ -454,9 +455,11 @@
     if (data_it.second->intent.has_value()) {
       DCHECK(data_it.second->intent.value());
       ::full_restore::SaveAppLaunchInfo(
-          file_path, std::make_unique<::app_restore::AppLaunchInfo>(
-                         app_id, event_flags, data_it.second->intent->Clone(),
-                         arc_session_id, display_id));
+          file_path,
+          std::make_unique<::app_restore::AppLaunchInfo>(
+              app_id, event_flags,
+              apps::ConvertMojomIntentToIntent(data_it.second->intent.value()),
+              arc_session_id, display_id));
     } else {
       ::full_restore::SaveAppLaunchInfo(
           file_path, std::make_unique<::app_restore::AppLaunchInfo>(
diff --git a/chrome/browser/ash/arc/input_overlay/constants.h b/chrome/browser/ash/arc/input_overlay/constants.h
index 57f3bf1..5db29cf 100644
--- a/chrome/browser/ash/arc/input_overlay/constants.h
+++ b/chrome/browser/ash/arc/input_overlay/constants.h
@@ -63,6 +63,9 @@
   kInfo,
   // |kError| is the type for error message.
   kError,
+  // |kInfoLabelFocus| is the type for info message when the |ActionLabel| is
+  // focused.
+  kInfoLabelFocus,
 };
 
 }  // namespace input_overlay
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
index f97ec857..5b938a40 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_label.cc
@@ -267,8 +267,8 @@
     static_cast<ActionView*>(parent())->ShowErrorMsg(
         l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_MISSING_BINDING), this);
   } else {
-    static_cast<ActionView*>(parent())->ShowInfoMsg(
-        l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_FOCUSED_KEY), this);
+    static_cast<ActionView*>(parent())->ShowLabelFocusInfoMsg(
+        l10n_util::GetStringUTF8(IDS_INPUT_OVERLAY_EDIT_FOCUSED_KEY));
   }
 }
 
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
index 3716c94..d4c28795 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_view.cc
@@ -109,6 +109,11 @@
   display_overlay_controller_->AddEditMessage(message, MessageType::kInfo);
 }
 
+void ActionView::ShowLabelFocusInfoMsg(const base::StringPiece& message) {
+  display_overlay_controller_->AddEditMessage(message,
+                                              MessageType::kInfoLabelFocus);
+}
+
 void ActionView::RemoveMessage() {
   display_overlay_controller_->RemoveEditMessage();
 }
diff --git a/chrome/browser/ash/arc/input_overlay/ui/action_view.h b/chrome/browser/ash/arc/input_overlay/ui/action_view.h
index 70b4a91..49d3740 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/action_view.h
+++ b/chrome/browser/ash/arc/input_overlay/ui/action_view.h
@@ -65,6 +65,7 @@
   // Show info/edu message.
   void ShowInfoMsg(const base::StringPiece& message,
                    ActionLabel* editing_label);
+  void ShowLabelFocusInfoMsg(const base::StringPiece& message);
   void RemoveMessage();
   // Change binding for |action| binding to |input_element| and set
   // |kEditedSuccess| on |action_label| if |action_label| is not nullptr.
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 4780870..f2c76f4 100644
--- a/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
+++ b/chrome/browser/ash/arc/input_overlay/ui/message_view.cc
@@ -83,6 +83,11 @@
           gfx::CreateVectorIcon(gfx::IconDescription(
               vector_icons::kErrorOutlineIcon, kIconSize, kErrorIconColor)));
       break;
+    case MessageType::kInfoLabelFocus:
+      SetImage(views::Button::STATE_NORMAL,
+               gfx::CreateVectorIcon(gfx::IconDescription(
+                   vector_icons::kKeyboardIcon, kIconSize, kInfoIconColor)));
+      break;
     default:
       NOTREACHED();
       break;
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn
index 97c1031..0e1d2035 100644
--- a/chrome/browser/ash/crosapi/BUILD.gn
+++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -97,6 +97,8 @@
     "drive_integration_service_ash.h",
     "echo_private_ash.cc",
     "echo_private_ash.h",
+    "emoji_picker_ash.cc",
+    "emoji_picker_ash.h",
     "environment_provider.cc",
     "environment_provider.h",
     "extension_info_private_ash.cc",
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc
index aef0cea..efc44ba 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.cc
+++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -43,6 +43,7 @@
 #include "chrome/browser/ash/crosapi/download_controller_ash.h"
 #include "chrome/browser/ash/crosapi/drive_integration_service_ash.h"
 #include "chrome/browser/ash/crosapi/echo_private_ash.h"
+#include "chrome/browser/ash/crosapi/emoji_picker_ash.h"
 #include "chrome/browser/ash/crosapi/extension_info_private_ash.h"
 #include "chrome/browser/ash/crosapi/feedback_ash.h"
 #include "chrome/browser/ash/crosapi/field_trial_service_ash.h"
@@ -177,6 +178,7 @@
       drive_integration_service_ash_(
           std::make_unique<DriveIntegrationServiceAsh>()),
       echo_private_ash_(std::make_unique<EchoPrivateAsh>()),
+      emoji_picker_ash_(std::make_unique<EmojiPickerAsh>()),
       extension_info_private_ash_(std::make_unique<ExtensionInfoPrivateAsh>()),
       feedback_ash_(std::make_unique<FeedbackAsh>()),
       field_trial_service_ash_(std::make_unique<FieldTrialServiceAsh>()),
@@ -726,6 +728,10 @@
     mojo::PendingReceiver<mojom::EchoPrivate> receiver) {
   echo_private_ash_->BindReceiver(std::move(receiver));
 }
+void CrosapiAsh::BindEmojiPicker(
+    mojo::PendingReceiver<mojom::EmojiPicker> receiver) {
+  emoji_picker_ash_->BindReceiver(std::move(receiver));
+}
 
 void CrosapiAsh::BindExtensionInfoPrivate(
     mojo::PendingReceiver<mojom::ExtensionInfoPrivate> receiver) {
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h
index 46bf122..2008219 100644
--- a/chrome/browser/ash/crosapi/crosapi_ash.h
+++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -12,6 +12,7 @@
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ash/crosapi/crosapi_id.h"
 #include "chromeos/crosapi/mojom/crosapi.mojom.h"
+#include "chromeos/crosapi/mojom/emoji_picker.mojom-forward.h"
 #include "chromeos/crosapi/mojom/task_manager.mojom.h"
 #include "media/gpu/buildflags.h"
 #include "mojo/public/cpp/bindings/generic_pending_receiver.h"
@@ -53,6 +54,7 @@
 class DownloadControllerAsh;
 class DriveIntegrationServiceAsh;
 class EchoPrivateAsh;
+class EmojiPickerAsh;
 class ExtensionInfoPrivateAsh;
 class FeedbackAsh;
 class FieldTrialServiceAsh;
@@ -173,6 +175,8 @@
       mojo::PendingReceiver<mojom::DriveIntegrationService> receiver) override;
   void BindEchoPrivate(
       mojo::PendingReceiver<mojom::EchoPrivate> receiver) override;
+  void BindEmojiPicker(
+      mojo::PendingReceiver<mojom::EmojiPicker> receiver) override;
   void BindExtensionInfoPrivate(
       mojo::PendingReceiver<mojom::ExtensionInfoPrivate> receiver) override;
   void BindExtensionPublisher(
@@ -311,6 +315,7 @@
   }
 
   EchoPrivateAsh* echo_private_ash() { return echo_private_ash_.get(); }
+  EmojiPickerAsh* emoji_picker_ash() { return emoji_picker_ash_.get(); }
 
   ExtensionInfoPrivateAsh* extension_info_private_ash() {
     return extension_info_private_ash_.get();
@@ -425,6 +430,7 @@
   std::unique_ptr<DownloadControllerAsh> download_controller_ash_;
   std::unique_ptr<DriveIntegrationServiceAsh> drive_integration_service_ash_;
   std::unique_ptr<EchoPrivateAsh> echo_private_ash_;
+  std::unique_ptr<EmojiPickerAsh> emoji_picker_ash_;
   std::unique_ptr<ExtensionInfoPrivateAsh> extension_info_private_ash_;
   std::unique_ptr<FeedbackAsh> feedback_ash_;
   std::unique_ptr<FieldTrialServiceAsh> field_trial_service_ash_;
diff --git a/chrome/browser/ash/crosapi/crosapi_util.cc b/chrome/browser/ash/crosapi/crosapi_util.cc
index 73394d8..c28030de 100644
--- a/chrome/browser/ash/crosapi/crosapi_util.cc
+++ b/chrome/browser/ash/crosapi/crosapi_util.cc
@@ -59,6 +59,7 @@
 #include "chromeos/crosapi/mojom/download_controller.mojom.h"
 #include "chromeos/crosapi/mojom/drive_integration_service.mojom.h"
 #include "chromeos/crosapi/mojom/echo_private.mojom.h"
+#include "chromeos/crosapi/mojom/emoji_picker.mojom.h"
 #include "chromeos/crosapi/mojom/extension_info_private.mojom.h"
 #include "chromeos/crosapi/mojom/feedback.mojom.h"
 #include "chromeos/crosapi/mojom/file_manager.mojom.h"
@@ -213,7 +214,7 @@
   return {T::Uuid_, T::Version_};
 }
 
-static_assert(crosapi::mojom::Crosapi::Version_ == 84,
+static_assert(crosapi::mojom::Crosapi::Version_ == 85,
               "If you add a new crosapi, please add it to "
               "kInterfaceVersionEntries below.");
 
@@ -249,6 +250,7 @@
     MakeInterfaceVersionEntry<crosapi::mojom::DownloadController>(),
     MakeInterfaceVersionEntry<crosapi::mojom::DriveIntegrationService>(),
     MakeInterfaceVersionEntry<crosapi::mojom::EchoPrivate>(),
+    MakeInterfaceVersionEntry<crosapi::mojom::EmojiPicker>(),
     MakeInterfaceVersionEntry<crosapi::mojom::ExtensionInfoPrivate>(),
     MakeInterfaceVersionEntry<crosapi::mojom::Feedback>(),
     MakeInterfaceVersionEntry<crosapi::mojom::FieldTrialService>(),
diff --git a/chrome/browser/ash/crosapi/emoji_picker_ash.cc b/chrome/browser/ash/crosapi/emoji_picker_ash.cc
new file mode 100644
index 0000000..915abc78
--- /dev/null
+++ b/chrome/browser/ash/crosapi/emoji_picker_ash.cc
@@ -0,0 +1,23 @@
+// 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/ash/crosapi/emoji_picker_ash.h"
+
+#include <utility>
+#include "ui/base/emoji/emoji_panel_helper.h"
+
+namespace crosapi {
+
+EmojiPickerAsh::EmojiPickerAsh() = default;
+EmojiPickerAsh::~EmojiPickerAsh() = default;
+
+void EmojiPickerAsh::BindReceiver(
+    mojo::PendingReceiver<mojom::EmojiPicker> pending_receiver) {
+  receivers_.Add(this, std::move(pending_receiver));
+}
+
+void EmojiPickerAsh::ShowEmojiPicker() {
+  ui::ShowEmojiPanel();
+}
+}  // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/emoji_picker_ash.h b/chrome/browser/ash/crosapi/emoji_picker_ash.h
new file mode 100644
index 0000000..864cb44
--- /dev/null
+++ b/chrome/browser/ash/crosapi/emoji_picker_ash.h
@@ -0,0 +1,36 @@
+// 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_ASH_CROSAPI_EMOJI_PICKER_ASH_H_
+#define CHROME_BROWSER_ASH_CROSAPI_EMOJI_PICKER_ASH_H_
+
+#include "base/memory/weak_ptr.h"
+#include "chromeos/crosapi/mojom/emoji_picker.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+
+namespace crosapi {
+
+// The ash-chrome implementation of the EmojiPicker crosapi interface.
+// This class must only be used from the main thread.
+class EmojiPickerAsh : public mojom::EmojiPicker {
+ public:
+  EmojiPickerAsh();
+  EmojiPickerAsh(const EmojiPickerAsh&) = delete;
+  EmojiPickerAsh& operator=(const EmojiPickerAsh&) = delete;
+  ~EmojiPickerAsh() override;
+
+  void BindReceiver(mojo::PendingReceiver<mojom::EmojiPicker> receiver);
+  // mojom::EmojiPicker
+  void ShowEmojiPicker() override;
+
+ private:
+  mojo::ReceiverSet<mojom::EmojiPicker> receivers_;
+
+  base::WeakPtrFactory<EmojiPickerAsh> weak_factory_{this};
+};
+
+}  // namespace crosapi
+
+#endif  // CHROME_BROWSER_ASH_CROSAPI_EMOJI_PICKER_ASH_H_
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc
index 8e6edc8a..e7644de 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.cc
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -4,11 +4,16 @@
 
 #include "chrome/browser/ash/file_manager/file_manager_string_util.h"
 
+#include <math.h>
+
 #include "ash/components/arc/arc_features.h"
 #include "ash/constants/ash_features.h"
+#include "ash/system/time/calendar_utils.h"
+#include "ash/system/time/date_helper.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
+#include "base/time/time.h"
 #include "base/values.h"
 #include "chrome/browser/ash/crostini/crostini_features.h"
 #include "chrome/browser/ash/login/demo_mode/demo_session.h"
@@ -945,6 +950,32 @@
   return dict;
 }
 
+int GetLocaleBasedWeekStart() {
+  // To avoid the DST difference, use a certain date here to calculate the week
+  // start, since there are no daylight saving starts/ends in June worldwide.
+  base::Time fixed_date;
+  bool result = base::Time::FromString("15 Jun 2021 12:00 GMT", &fixed_date);
+  DCHECK(result);
+  int local_day_of_week = 2;  // 15 Jun 2021 is Tuesday.
+  // Adjust local_day_of_week according to the current timezone. We are using
+  // 12:00pm UTC above, so only need to check if the local time difference is
+  // larger than +12 or not, all other differences fall into the same day.
+  // Note: timezone difference will never be lower than -12.
+  base::TimeDelta time_difference =
+      ash::DateHelper::GetInstance()->GetTimeDifference(fixed_date);
+  if (time_difference.InHours() >= 12) {
+    // Local time is one day after, e.g. it's Wednesday.
+    local_day_of_week += 1;
+  }
+
+  const int day_of_week = ash::calendar_utils::GetDayOfWeekInt(fixed_date);
+  // We know the fixed date is Thursday, day_of_week is between 1 and 7.
+  // * if day_of_week is 4, then Monday is the start of the week, so return 1;
+  // * if day_of_week is 5, then Sunday is the start of the week, so return 0;
+  // * if day_of_week is 6, then Saturday is the start of the week, so return 6;
+  return fmod(local_day_of_week - (day_of_week - 1) + 7, 7);
+}
+
 void AddFileManagerFeatureStrings(const std::string& locale,
                                   Profile* profile,
                                   base::Value::Dict* dict) {
@@ -989,4 +1020,5 @@
             base::FeatureList::IsEnabled(chromeos::features::kGuestOsFiles));
 
   dict->Set("UI_LOCALE", locale);
+  dict->Set("WEEK_START_FROM", GetLocaleBasedWeekStart());
 }
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.h b/chrome/browser/ash/file_manager/file_manager_string_util.h
index 25dca72..42cb0ad 100644
--- a/chrome/browser/ash/file_manager/file_manager_string_util.h
+++ b/chrome/browser/ash/file_manager/file_manager_string_util.h
@@ -13,6 +13,10 @@
 
 base::Value::Dict GetFileManagerStrings();
 
+// This function will return a number between 0 (Sunday) and 6 (Saturday)
+// to indicate which day is the start of week based on the current locale.
+int GetLocaleBasedWeekStart();
+
 void AddFileManagerFeatureStrings(const std::string& locale,
                                   Profile* profile,
                                   base::Value::Dict* dict);
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util_unittest.cc b/chrome/browser/ash/file_manager/file_manager_string_util_unittest.cc
new file mode 100644
index 0000000..d9a2131
--- /dev/null
+++ b/chrome/browser/ash/file_manager/file_manager_string_util_unittest.cc
@@ -0,0 +1,63 @@
+// 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/ash/file_manager/file_manager_string_util.h"
+
+#include "ash/components/settings/timezone_settings.h"
+#include "ash/system/time/date_helper.h"
+#include "base/i18n/rtl.h"
+#include "chrome/test/base/chrome_ash_test_base.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+class FileManagerStringUtilTest : public ChromeAshTestBase {
+ public:
+  FileManagerStringUtilTest(const FileManagerStringUtilTest&) = delete;
+  FileManagerStringUtilTest& operator=(const FileManagerStringUtilTest&) =
+      delete;
+  FileManagerStringUtilTest() = default;
+  ~FileManagerStringUtilTest() override = default;
+
+  void SetDefaultLocale(const std::string& locale) {
+    base::i18n::SetICUDefaultLocale(locale);
+    ash::DateHelper::GetInstance()->ResetForTesting();
+  }
+
+  void SetTimezone(const std::u16string& timezone_id) {
+    ash::system::TimezoneSettings::GetInstance()->SetTimezoneFromID(
+        timezone_id);
+  }
+};
+
+TEST_F(FileManagerStringUtilTest, GetLocaleBasedWeekStart_Locale) {
+  const struct DateTestData {
+    const char* locale;
+    int start_of_week;
+  } kDateTestData[] = {
+      // Australia uses Monday as the start day of the week.
+      {"en_AU", 1},
+      // United States uses Sunday as the start day of the week.
+      {"en_US", 0},
+      // Afghanistan uses Saturday as the start day of the week.
+      {"ps-AF", 6},
+      {"pa-PK", 0}};
+
+  for (const auto& test : kDateTestData) {
+    SetDefaultLocale(test.locale);
+    EXPECT_EQ(GetLocaleBasedWeekStart(), test.start_of_week);
+  }
+}
+
+TEST_F(FileManagerStringUtilTest, GetLocaleBasedWeekStart_Timezone) {
+  const std::u16string kTimezoneIds[] = {
+      u"GMT",      u"PST",      u"GMT+0800", u"GMT+1000", u"GMT+1300",
+      u"GMT+1400", u"GMT-0800", u"GMT-1100", u"GMT-1200",
+  };
+
+  SetDefaultLocale("en_AU");
+  for (const auto& timezone_id : kTimezoneIds) {
+    SetTimezone(timezone_id);
+    // Regardless the timezone, week always starts with Monday for AU locale.
+    EXPECT_EQ(GetLocaleBasedWeekStart(), 1);
+  }
+}
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
index 4e0c56a0..e335ce9 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.cc
@@ -200,11 +200,39 @@
 ProfileAuthServersSyncBridge::ApplySyncChanges(
     std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
     syncer::EntityChangeList entity_changes) {
+  std::unique_ptr<syncer::ModelTypeStore::WriteBatch> batch =
+      store_->CreateWriteBatch();
+  for (const std::unique_ptr<syncer::EntityChange>& change : entity_changes) {
+    const std::string uri = change->storage_key();
+    if (change->type() == syncer::EntityChange::ACTION_DELETE) {
+      batch->DeleteData(uri);
+      servers_uris_.erase(uri);
+    } else {
+      batch->WriteData(uri, change->data()
+                                .specifics.printers_authorization_server()
+                                .SerializeAsString());
+      servers_uris_.insert(uri);
+    }
+  }
+
+  batch->TakeMetadataChangesFrom(std::move(metadata_change_list));
+  store_->CommitWriteBatch(
+      std::move(batch), base::BindOnce(&ProfileAuthServersSyncBridge::OnCommit,
+                                       weak_ptr_factory_.GetWeakPtr()));
+
   return absl::nullopt;
 }
 
 void ProfileAuthServersSyncBridge::GetData(StorageKeyList storage_keys,
-                                           DataCallback callback) {}
+                                           DataCallback callback) {
+  auto batch = std::make_unique<syncer::MutableDataBatch>();
+  for (const std::string& key : storage_keys) {
+    if (base::Contains(servers_uris_, key)) {
+      batch->Put(key, ToEntityDataPtr(key));
+    }
+  }
+  std::move(callback).Run(std::move(batch));
+}
 
 void ProfileAuthServersSyncBridge::GetAllDataForDebugging(
     DataCallback callback) {
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
index f245f5e..5b022e0 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h
@@ -66,6 +66,20 @@
   // list of trusted Authorization Servers.
   void AddAuthorizationServer(const chromeos::Uri& server);
 
+  // Implementation of ModelTypeSyncBridge interface.
+  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
+      override;
+  absl::optional<syncer::ModelError> MergeSyncData(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_data) override;
+  absl::optional<syncer::ModelError> ApplySyncChanges(
+      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
+      syncer::EntityChangeList entity_changes) override;
+  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
+  void GetAllDataForDebugging(DataCallback callback) override;
+  std::string GetClientTag(const syncer::EntityData& entity_data) override;
+  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
+
  private:
   ProfileAuthServersSyncBridge(
       std::unique_ptr<syncer::ModelTypeChangeProcessor> change_processor,
@@ -85,20 +99,6 @@
   void OnReadAllMetadata(const absl::optional<syncer::ModelError>& error,
                          std::unique_ptr<syncer::MetadataBatch> metadata_batch);
 
-  // Implementation of ModelTypeSyncBridge interface.
-  std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList()
-      override;
-  absl::optional<syncer::ModelError> MergeSyncData(
-      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
-      syncer::EntityChangeList entity_data) override;
-  absl::optional<syncer::ModelError> ApplySyncChanges(
-      std::unique_ptr<syncer::MetadataChangeList> metadata_change_list,
-      syncer::EntityChangeList entity_changes) override;
-  void GetData(StorageKeyList storage_keys, DataCallback callback) override;
-  void GetAllDataForDebugging(DataCallback callback) override;
-  std::string GetClientTag(const syncer::EntityData& entity_data) override;
-  std::string GetStorageKey(const syncer::EntityData& entity_data) override;
-
   // Callback to handle commit errors.
   void OnCommit(const absl::optional<syncer::ModelError>& error);
 
diff --git a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
index d35f30a5..74d2d0e3 100644
--- a/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
+++ b/chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge_unittest.cc
@@ -5,9 +5,13 @@
 #include "chrome/browser/ash/printing/oauth2/profile_auth_servers_sync_bridge.h"
 
 #include <memory>
+#include <string>
+#include <vector>
 
 #include "base/run_loop.h"
 #include "base/test/bind.h"
+#include "base/test/gmock_move_support.h"
+#include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
 #include "chromeos/printing/uri.h"
 #include "components/sync/model/data_batch.h"
@@ -55,7 +59,6 @@
   }
 
   void DoInitialMerge(const std::vector<std::string>& records) {
-    syncer::ModelTypeSyncBridge* bridge = bridge_.get();
     syncer::EntityChangeList data_change_list;
     for (const std::string& uri : records) {
       data_change_list.push_back(
@@ -63,19 +66,34 @@
     }
     ON_CALL(mock_processor_, IsTrackingMetadata())
         .WillByDefault(testing::Return(true));
-    bridge->MergeSyncData(bridge->CreateMetadataChangeList(),
-                          std::move(data_change_list));
+    absl::optional<syncer::ModelError> error = bridge_->MergeSyncData(
+        bridge_->CreateMetadataChangeList(), std::move(data_change_list));
+    ASSERT_FALSE(error);
+  }
+
+  void DoApplySyncChanges(const std::vector<std::string>& added,
+                          const std::vector<std::string>& deleted) {
+    syncer::EntityChangeList data_change_list;
+    for (const std::string& uri : added) {
+      data_change_list.push_back(
+          syncer::EntityChange::CreateAdd(uri, ToEntityData(uri)));
+    }
+    for (const std::string& uri : deleted) {
+      data_change_list.push_back(syncer::EntityChange::CreateDelete(uri));
+    }
+    absl::optional<syncer::ModelError> error = bridge_->ApplySyncChanges(
+        bridge_->CreateMetadataChangeList(), std::move(data_change_list));
+    ASSERT_FALSE(error);
   }
 
   std::vector<std::string> GetAllData() {
     std::unique_ptr<syncer::DataBatch> output;
-    syncer::ModelTypeSyncBridge* bridge = bridge_.get();
     base::RunLoop loop;
     auto callback = [&output, &loop](std::unique_ptr<syncer::DataBatch> data) {
       output = std::move(data);
       loop.Quit();
     };
-    bridge->GetAllDataForDebugging(base::BindLambdaForTesting(callback));
+    bridge_->GetAllDataForDebugging(base::BindLambdaForTesting(callback));
     loop.Run();
 
     std::vector<std::string> uris;
@@ -143,5 +161,47 @@
   EXPECT_EQ(uris, (std::vector{uri_1, uri_2}));
 }
 
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest, ApplySyncChanges) {
+  const std::string uri_1 = "https://a.b.c/123";
+  const std::string uri_2 = "https://def:123/gh";
+  const std::string uri_3 = "https://xyz/ab";
+  CreateBridge();
+  DoInitialMerge({});
+
+  DoApplySyncChanges(/*added=*/{uri_1, uri_2}, /*deleted=*/{});
+  std::vector<std::string> uris = GetAllData();
+  EXPECT_EQ(uris, (std::vector{uri_1, uri_2}));
+
+  DoApplySyncChanges(/*added=*/{uri_3}, /*deleted=*/{uri_1});
+  uris = GetAllData();
+  EXPECT_EQ(uris, (std::vector{uri_2, uri_3}));
+}
+
+TEST_F(PrintingOAuth2ProfileAuthServersSyncBridgeTest, GetData) {
+  const std::string uri_1 = "https://a.b.c/123";
+  const std::string uri_2 = "https://def:123/gh";
+  const std::string uri_3 = "https://xyz/ab";
+  CreateBridge();
+  DoInitialMerge({uri_1, uri_2});
+
+  std::unique_ptr<syncer::DataBatch> output;
+  base::MockOnceCallback<void(std::unique_ptr<syncer::DataBatch> data_batch)>
+      callback;
+  EXPECT_CALL(callback, Run).WillOnce(MoveArg(&output));
+  bridge_->GetData({uri_1, uri_3}, callback.Get());
+
+  ASSERT_TRUE(output);
+  std::vector<syncer::KeyAndData> data;
+  while (output->HasNext()) {
+    data.push_back(output->Next());
+  }
+  ASSERT_EQ(data.size(), 1);
+  EXPECT_EQ(data[0].first, uri_1);
+  ASSERT_TRUE(data[0].second);
+  EXPECT_EQ(
+      data[0].second->specifics.mutable_printers_authorization_server()->uri(),
+      uri_1);
+}
+
 }  // namespace
 }  // namespace ash::printing::oauth2
diff --git a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
index 587fd397..13d355c 100644
--- a/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/media_app/media_web_app_info.cc
@@ -116,10 +116,10 @@
 const apps::AppLaunchParams PickFileFromParams(
     const apps::AppLaunchParams& params,
     size_t index) {
-  return apps::AppLaunchParams(params.app_id, params.container,
-                               params.disposition, params.launch_source,
-                               params.display_id, {params.launch_files[index]},
-                               params.intent ? params.intent.Clone() : nullptr);
+  return apps::AppLaunchParams(
+      params.app_id, params.container, params.disposition, params.launch_source,
+      params.display_id, {params.launch_files[index]},
+      params.intent ? params.intent->Clone() : nullptr);
 }
 
 }  // namespace
diff --git a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
index 2b9f05d..f0bbb710 100644
--- a/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
+++ b/chrome/browser/ash/web_applications/os_feedback_system_web_app_info.cc
@@ -117,7 +117,7 @@
     apps::AppLaunchParams app_params(
         params.app_id, params.container, params.disposition,
         params.launch_source, params.display_id, params.launch_files,
-        params.intent ? params.intent.Clone() : nullptr);
+        params.intent ? params.intent->Clone() : nullptr);
     // Take a screenshot and launch the app afterward.
     ash::OsFeedbackScreenshotManager::GetInstance()->TakeScreenshot(
         base::BindOnce(&OSFeedbackAppDelegate::OnScreenshotTaken,
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
index 841dff0..e2faa865 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.cc
@@ -212,12 +212,6 @@
   NOTIMPLEMENTED();
 }
 
-void BackgroundFetchDelegateImpl::ChangeSchedule(
-    const offline_items_collection::ContentId& id,
-    absl::optional<offline_items_collection::OfflineItemSchedule> schedule) {
-  NOTIMPLEMENTED();
-}
-
 download::BackgroundDownloadService*
 BackgroundFetchDelegateImpl::GetDownloadService() {
   return BackgroundDownloadServiceFactory::GetInstance()->GetForKey(
diff --git a/chrome/browser/background_fetch/background_fetch_delegate_impl.h b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
index 92a0979..c1534d0e 100644
--- a/chrome/browser/background_fetch/background_fetch_delegate_impl.h
+++ b/chrome/browser/background_fetch/background_fetch_delegate_impl.h
@@ -67,10 +67,6 @@
   void RenameItem(const offline_items_collection::ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(
-      const offline_items_collection::ContentId& id,
-      absl::optional<offline_items_collection::OfflineItemSchedule> schedule)
-      override;
 
  protected:
   // BackgroundFetchDelegateBase:
diff --git a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
index dbae42cf..13549afb 100644
--- a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
+++ b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
@@ -392,7 +392,7 @@
     auto page_content_annotations_service =
         std::make_unique<optimization_guide::PageContentAnnotationsService>(
             "en-US", optimization_guide_model_providers_.at(profile).get(),
-            history_service, nullptr, base::FilePath(), nullptr);
+            history_service, nullptr, base::FilePath(), nullptr, nullptr);
 
     page_content_annotations_service->OverridePageContentAnnotatorForTesting(
         &test_page_content_annotator_);
diff --git a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
index 09fe5ed..b9cea713 100644
--- a/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
+++ b/chrome/browser/browsing_topics/browsing_topics_service_browsertest.cc
@@ -330,7 +330,7 @@
     auto page_content_annotations_service =
         std::make_unique<optimization_guide::PageContentAnnotationsService>(
             "en-US", optimization_guide_model_providers_.at(profile).get(),
-            history_service, nullptr, base::FilePath(), nullptr);
+            history_service, nullptr, base::FilePath(), nullptr, nullptr);
 
     page_content_annotations_service->OverridePageContentAnnotatorForTesting(
         &test_page_content_annotator_);
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 8e12b8a2..99ba1b93 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -2474,6 +2474,7 @@
     "../ash/file_manager/delete_io_task_unittest.cc",
     "../ash/file_manager/documents_provider_root_manager_unittest.cc",
     "../ash/file_manager/empty_trash_io_task_unittest.cc",
+    "../ash/file_manager/file_manager_string_util_unittest.cc",
     "../ash/file_manager/file_tasks_notifier_unittest.cc",
     "../ash/file_manager/file_tasks_unittest.cc",
     "../ash/file_manager/file_watcher_unittest.cc",
diff --git a/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_ash_browsertest.cc b/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_ash_browsertest.cc
new file mode 100644
index 0000000..2e6638b3
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_ash_browsertest.cc
@@ -0,0 +1,117 @@
+// 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/ash/login/test/cryptohome_mixin.h"
+#include "chrome/browser/ash/policy/affiliation/affiliation_mixin.h"
+#include "chrome/browser/ash/policy/affiliation/affiliation_test_helper.h"
+#include "chrome/browser/ash/policy/core/device_policy_cros_browser_test.h"
+#include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/pref_names.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/test_launcher.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace {
+
+// Browser test that validates extension installation status when the
+// `InsightsExtensionEnabled` policy is set/unset. Inheriting from
+// DevicePolicyCrosBrowserTest enables use of AffiliationMixin for setting up
+// profile/device affiliation. Only available in Ash.
+class ContactCenterInsightsExtensionManagerBrowserTest
+    : public ::policy::DevicePolicyCrosBrowserTest {
+ protected:
+  ContactCenterInsightsExtensionManagerBrowserTest() {
+    crypto_home_mixin_.MarkUserAsExisting(affiliation_mixin_.account_id());
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    ::policy::AffiliationTestHelper::AppendCommandLineSwitchesForLoginManager(
+        command_line);
+    ::policy::DevicePolicyCrosBrowserTest::SetUpCommandLine(command_line);
+  }
+
+  void SetUpOnMainThread() override {
+    ::policy::DevicePolicyCrosBrowserTest::SetUpOnMainThread();
+    if (content::IsPreTest()) {
+      // Preliminary setup - set up affiliated user
+      ::policy::AffiliationTestHelper::PreLoginUser(
+          affiliation_mixin_.account_id());
+      return;
+    }
+
+    // Login as affiliated user otherwise
+    ::policy::AffiliationTestHelper::LoginUser(affiliation_mixin_.account_id());
+  }
+
+  Profile* profile() const {
+    return ash::ProfileHelper::Get()->GetProfileByAccountId(
+        affiliation_mixin_.account_id());
+  }
+
+  void SetPrefValue(bool value) {
+    profile()->GetPrefs()->SetBoolean(::prefs::kInsightsExtensionEnabled,
+                                      value);
+    content::RunAllTasksUntilIdle();
+  }
+
+  ::policy::DevicePolicyCrosTestHelper test_helper_;
+  ::policy::AffiliationMixin affiliation_mixin_{&mixin_host_, &test_helper_};
+  ash::CryptohomeMixin crypto_home_mixin_{&mixin_host_};
+};
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       PRE_ExtensionUnloadedByDefault) {
+  // Dummy case that sets up the affiliated user.
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       ExtensionUnloadedByDefault) {
+  auto* const extension_registry =
+      ::extensions::ExtensionRegistry::Get(profile());
+  EXPECT_FALSE(extension_registry->GetInstalledExtension(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       PRE_InstallExtensionWhenPrefSet) {
+  // Dummy case that sets up the affiliated user.
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       InstallExtensionWhenPrefSet) {
+  SetPrefValue(true);
+  auto* const extension_registry =
+      ::extensions::ExtensionRegistry::Get(profile());
+  EXPECT_TRUE(extension_registry->enabled_extensions().GetByID(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       PRE_ExtensionUninstalledWhenPrefUnset) {
+  // Dummy case that sets up the affiliated user.
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       ExtensionUninstalledWhenPrefUnset) {
+  auto* const extension_registry =
+      ::extensions::ExtensionRegistry::Get(profile());
+
+  // Set pref to enable extension.
+  SetPrefValue(true);
+  EXPECT_TRUE(extension_registry->enabled_extensions().GetByID(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+
+  // Unset pref and verify extension is unloaded
+  SetPrefValue(false);
+  EXPECT_FALSE(extension_registry->GetInstalledExtension(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+}  // namespace
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_lacros_browsertest.cc b/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_lacros_browsertest.cc
new file mode 100644
index 0000000..0d4d931
--- /dev/null
+++ b/chrome/browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_lacros_browsertest.cc
@@ -0,0 +1,85 @@
+// 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/browser_process.h"
+#include "chrome/browser/extensions/extension_browsertest.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/common/extensions/extension_constants.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/startup/browser_init_params.h"
+#include "components/policy/core/common/policy_loader_lacros.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/browser/extension_registry.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace {
+
+constexpr char kFakeDMToken[] = "fake-dm-token";
+constexpr char kFakeProfileClientId[] = "fake-profile-client-id";
+constexpr char kAffiliationId[] = "affiliation-id";
+constexpr char kDomain[] = "domain.com";
+
+void SetupUserDeviceAffiliation() {
+  ::enterprise_management::PolicyData profile_policy_data;
+  profile_policy_data.add_user_affiliation_ids(kAffiliationId);
+  profile_policy_data.set_managed_by(kDomain);
+  profile_policy_data.set_device_id(kFakeProfileClientId);
+  profile_policy_data.set_request_token(kFakeDMToken);
+  ::policy::PolicyLoaderLacros::set_main_user_policy_data_for_testing(
+      std::move(profile_policy_data));
+
+  ::crosapi::mojom::BrowserInitParamsPtr init_params =
+      ::crosapi::mojom::BrowserInitParams::New();
+  init_params->device_properties = crosapi::mojom::DeviceProperties::New();
+  init_params->device_properties->device_dm_token = kFakeDMToken;
+  init_params->device_properties->device_affiliation_ids = {kAffiliationId};
+  BrowserInitParams::SetInitParamsForTests(std::move(init_params));
+}
+
+// Browser test that validates extension installation status when the
+// `InsightsExtensionEnabled` policy is set/unset on Lacros.
+class ContactCenterInsightsExtensionManagerBrowserTest
+    : public ::extensions::ExtensionBrowserTest {
+ protected:
+  void SetUpInProcessBrowserTestFixture() override {
+    ::extensions::ExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
+    SetupUserDeviceAffiliation();
+  }
+
+  void SetPrefValue(bool value) {
+    profile()->GetPrefs()->SetBoolean(::prefs::kInsightsExtensionEnabled,
+                                      value);
+    content::RunAllTasksUntilIdle();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       ExtensionUnloadedByDefault) {
+  EXPECT_FALSE(extension_registry()->GetInstalledExtension(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       InstallExtensionWhenPrefSet) {
+  SetPrefValue(true);
+  EXPECT_TRUE(extension_registry()->enabled_extensions().GetByID(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+IN_PROC_BROWSER_TEST_F(ContactCenterInsightsExtensionManagerBrowserTest,
+                       ExtensionUninstalledWhenPrefUnset) {
+  // Set pref to enable extension.
+  SetPrefValue(true);
+  EXPECT_TRUE(extension_registry()->enabled_extensions().GetByID(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+
+  // Unset pref and verify extension is unloaded
+  SetPrefValue(false);
+  EXPECT_FALSE(extension_registry()->GetInstalledExtension(
+      ::extension_misc::kContactCenterInsightsExtensionId));
+}
+
+}  // namespace
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
index 66f8e28..e0ce3fb 100644
--- a/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
+++ b/chrome/browser/chromeos/extensions/login_screen/login/cleanup/extension_cleanup_handler_unittest.cc
@@ -128,10 +128,11 @@
   }
 
   void SetupExemptList() {
-    const base::Value exemptList[]{base::Value(kExemptExtensionId)};
+    base::Value::List exempt_list;
+    exempt_list.Append(kExemptExtensionId);
     mock_prefs_->SetManagedPref(
         prefs::kRestrictedManagedGuestSessionExtensionCleanupExemptList,
-        std::make_unique<base::ListValue>(exemptList));
+        base::Value(std::move(exempt_list)));
   }
 
   content::BrowserTaskEnvironment task_environment_;
diff --git a/chrome/browser/content_index/content_index_provider_impl.cc b/chrome/browser/content_index/content_index_provider_impl.cc
index a222d82f..528d4ce 100644
--- a/chrome/browser/content_index/content_index_provider_impl.cc
+++ b/chrome/browser/content_index/content_index_provider_impl.cc
@@ -401,9 +401,3 @@
                                           RenameCallback callback) {
   NOTREACHED();
 }
-
-void ContentIndexProviderImpl::ChangeSchedule(
-    const ContentId& id,
-    absl::optional<OfflineItemSchedule> schedule) {
-  NOTREACHED();
-}
diff --git a/chrome/browser/content_index/content_index_provider_impl.h b/chrome/browser/content_index/content_index_provider_impl.h
index 358c091..cc6f252 100644
--- a/chrome/browser/content_index/content_index_provider_impl.h
+++ b/chrome/browser/content_index/content_index_provider_impl.h
@@ -74,10 +74,6 @@
   void RenameItem(const offline_items_collection::ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(
-      const offline_items_collection::ContentId& id,
-      absl::optional<offline_items_collection::OfflineItemSchedule> schedule)
-      override;
 
   void SetIconSizesForTesting(std::vector<gfx::Size> icon_sizes) {
     icon_sizes_for_testing_ = std::move(icon_sizes);
diff --git a/chrome/browser/download/android/BUILD.gn b/chrome/browser/download/android/BUILD.gn
index 4f16b89..efc495e1 100644
--- a/chrome/browser/download/android/BUILD.gn
+++ b/chrome/browser/download/android/BUILD.gn
@@ -48,7 +48,6 @@
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogChoice.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogController.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogCoordinator.java",
-    "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelper.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogProperties.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogView.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLocationCustomView.java",
@@ -196,7 +195,6 @@
     "java/src/org/chromium/chrome/browser/download/DownloadLaterMetricsUnitTest.java",
     "java/src/org/chromium/chrome/browser/download/DownloadLocationDialogMetricsUnitTest.java",
     "java/src/org/chromium/chrome/browser/download/dialogs/DownloadDialogUtilsUnitTest.java",
-    "java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelperUnitTest.java",
   ]
 
   deps = [
diff --git a/chrome/browser/download/android/download_manager_service.cc b/chrome/browser/download/android/download_manager_service.cc
index ab24ddf..13f4109 100644
--- a/chrome/browser/download/android/download_manager_service.cc
+++ b/chrome/browser/download/android/download_manager_service.cc
@@ -807,31 +807,6 @@
   item->Rename(base::FilePath(target_name), std::move(callback));
 }
 
-void DownloadManagerService::ChangeSchedule(
-    JNIEnv* env,
-    const JavaParamRef<jobject>& obj,
-    const JavaParamRef<jstring>& id,
-    jboolean only_on_wifi,
-    jlong start_time,
-    const JavaParamRef<jobject>& j_profile_key) {
-  std::string download_guid = ConvertJavaStringToUTF8(id);
-  download::DownloadItem* item = GetDownload(
-      download_guid, ProfileKeyAndroid::FromProfileKeyAndroid(j_profile_key));
-  if (!item)
-    return;
-
-  absl::optional<DownloadSchedule> download_schedule;
-  if (only_on_wifi) {
-    download_schedule = absl::make_optional<DownloadSchedule>(
-        true /*only_on_wifi*/, absl::nullopt);
-  } else if (start_time > 0) {
-    download_schedule = absl::make_optional<DownloadSchedule>(
-        false /*only_on_wifi*/, base::Time::FromJavaTime(start_time));
-  }
-
-  item->OnDownloadScheduleChanged(std::move(download_schedule));
-}
-
 void DownloadManagerService::CreateInterruptedDownloadForTest(
     JNIEnv* env,
     jobject obj,
diff --git a/chrome/browser/download/android/download_manager_service.h b/chrome/browser/download/android/download_manager_service.h
index eb76199..cc87f66 100644
--- a/chrome/browser/download/android/download_manager_service.h
+++ b/chrome/browser/download/android/download_manager_service.h
@@ -126,15 +126,6 @@
                       const JavaParamRef<jobject>& callback,
                       const JavaParamRef<jobject>& j_profile_key);
 
-  // Called to change the download schedule of a download item that has GUID
-  // equal to |id|.
-  void ChangeSchedule(JNIEnv* env,
-                      const JavaParamRef<jobject>& obj,
-                      const JavaParamRef<jstring>& id,
-                      jboolean only_on_wifi,
-                      jlong start_time,
-                      const JavaParamRef<jobject>& j_profile_key);
-
   // Returns whether or not the given download can be opened by the browser.
   bool IsDownloadOpenableInBrowser(JNIEnv* env,
                                    jobject obj,
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelper.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelper.java
deleted file mode 100644
index 88367b1..0000000
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelper.java
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.download.dialogs;
-
-import android.content.Context;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.NonNull;
-
-import org.chromium.base.Callback;
-import org.chromium.chrome.browser.download.DownloadDialogBridge;
-import org.chromium.chrome.browser.download.DownloadLaterMetrics;
-import org.chromium.chrome.browser.download.DownloadLaterMetrics.DownloadLaterUiEvent;
-import org.chromium.components.offline_items_collection.OfflineItemSchedule;
-import org.chromium.components.prefs.PrefService;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * A wrapper of {@link DownloadLaterDialogCoordinator}, always use the same Android {@link Context}
- * and relevant dependencies, and supports to show dialog based on a {@link
- * org.chromium.components.offline_items_collection.OfflineItem}.
- */
-public class DownloadLaterDialogHelper implements DownloadLaterDialogController {
-    /**
-     * Defines the caller of {@link DownloadLaterDialogHelper}. Used in metrics recording.
-     */
-    @IntDef({Source.DOWNLOAD_HOME, Source.DOWNLOAD_INFOBAR})
-    public @interface Source {
-        int DOWNLOAD_HOME = 0;
-        int DOWNLOAD_INFOBAR = 1;
-    }
-
-    private final Context mContext;
-    private final ModalDialogManager mModalDialogManager;
-    private final PrefService mPrefService;
-    private final DownloadLaterDialogCoordinator mDownloadLaterDialog;
-
-    private Callback<OfflineItemSchedule> mCallback;
-    private @Source int mSource;
-
-    /**
-     * Creates the download later dialog helper.
-     * @param context The {@link Context} associated with the dialog.
-     * @param manager The {@link ModalDialogManager} to show the modal dialog.
-     * @param prefService Used to update user preferences.
-     * @return The download later dialog helper.
-     */
-    public static DownloadLaterDialogHelper create(
-            Context context, ModalDialogManager manager, PrefService prefService) {
-        DownloadDateTimePickerDialog dateTimePicker = new DownloadDateTimePickerDialogImpl();
-        DownloadLaterDialogCoordinator dialog = new DownloadLaterDialogCoordinator(dateTimePicker);
-        dateTimePicker.initialize(dialog);
-        return new DownloadLaterDialogHelper(context, manager, prefService, dialog);
-    }
-
-    DownloadLaterDialogHelper(Context context, ModalDialogManager manager, PrefService prefService,
-            DownloadLaterDialogCoordinator downloadLaterDialog) {
-        mContext = context;
-        mModalDialogManager = manager;
-        mPrefService = prefService;
-        mDownloadLaterDialog = downloadLaterDialog;
-        mDownloadLaterDialog.initialize(this);
-    }
-
-    /**
-     * Shows a download later dialog when the user wants to change the {@link OfflineItemSchedule}.
-     * @param currentSchedule The current {@link OfflineItemSchedule}.
-     * @param source The caller of this function, used to collect metrics.
-     * @param callback The callback to reply the new schedule selected by the user. May reply null
-     *                 if the user cancels the dialog.
-     */
-    public void showChangeScheduleDialog(@NonNull final OfflineItemSchedule currentSchedule,
-            @Source int source, Callback<OfflineItemSchedule> callback) {
-        @DownloadLaterDialogChoice
-        int initialChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
-        initialChoice = currentSchedule.onlyOnWifi ? DownloadLaterDialogChoice.ON_WIFI
-                                                   : DownloadLaterDialogChoice.DOWNLOAD_LATER;
-
-        mCallback = callback;
-        mSource = source;
-        boolean shouldShowDateTimePicker = DownloadDialogBridge.shouldShowDateTimePicker();
-        if (!shouldShowDateTimePicker
-                && initialChoice == DownloadLaterDialogChoice.DOWNLOAD_LATER) {
-            initialChoice = DownloadLaterDialogChoice.DOWNLOAD_NOW;
-        }
-        PropertyModel.Builder builder =
-                new PropertyModel.Builder(DownloadLaterDialogProperties.ALL_KEYS)
-                        .with(DownloadLaterDialogProperties.CONTROLLER, mDownloadLaterDialog)
-                        .with(DownloadLaterDialogProperties.INITIAL_CHOICE, initialChoice)
-                        .with(DownloadLaterDialogProperties.SHOW_DATE_TIME_PICKER_OPTION,
-                                shouldShowDateTimePicker);
-
-        // Set the previously selected time to the date time picker UI.
-        if (currentSchedule.startTimeMs > 0) {
-            builder.with(DownloadDateTimePickerDialogProperties.INITIAL_TIME,
-                    currentSchedule.startTimeMs);
-        }
-
-        mDownloadLaterDialog.showDialog(
-                mContext, mModalDialogManager, mPrefService, builder.build());
-    }
-
-    /**
-     * Destroys the download later dialog.
-     */
-    public void destroy() {
-        mDownloadLaterDialog.destroy();
-    }
-
-    // DownloadLaterDialogController implementation.
-    @Override
-    public void onDownloadLaterDialogComplete(int choice, long startTime) {
-        if (mCallback == null) return;
-
-        recordDialogMetrics(true /*complete*/, choice);
-        OfflineItemSchedule schedule =
-                new OfflineItemSchedule(choice == DownloadLaterDialogChoice.ON_WIFI, startTime);
-        mCallback.onResult(schedule);
-        mCallback = null;
-    }
-
-    @Override
-    public void onDownloadLaterDialogCanceled() {
-        if (mCallback == null) return;
-
-        recordDialogMetrics(false /*complete*/, DownloadLaterDialogChoice.CANCELLED);
-        mCallback.onResult(null);
-        mCallback = null;
-    }
-
-    @Override
-    public void onEditLocationClicked() {
-        // Do nothing, no edit location text for the change schedule dialog.
-    }
-
-    // Collect complete or cancel metrics based on the source of the dialog.
-    private void recordDialogMetrics(boolean complete, @DownloadLaterDialogChoice int choice) {
-        switch (mSource) {
-            case Source.DOWNLOAD_HOME:
-                if (complete) {
-                    DownloadLaterMetrics.recordDownloadHomeChangeScheduleChoice(choice);
-                } else {
-                    DownloadLaterMetrics.recordDownloadLaterUiEvent(
-                            DownloadLaterUiEvent.DOWNLOAD_HOME_CHANGE_SCHEDULE_CANCEL);
-                }
-                break;
-            case Source.DOWNLOAD_INFOBAR:
-                if (complete) {
-                    DownloadLaterMetrics.recordInfobarChangeScheduleChoice(choice);
-                } else {
-                    DownloadLaterMetrics.recordDownloadLaterUiEvent(
-                            DownloadLaterUiEvent.DOWNLOAD_INFOBAR_CHANGE_SCHEDULE_CANCEL);
-                }
-                break;
-            default:
-                assert false : "Unknown source, can't collect metrics.";
-                return;
-        }
-    }
-}
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelperUnitTest.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelperUnitTest.java
deleted file mode 100644
index 3c6e1bf8..0000000
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/dialogs/DownloadLaterDialogHelperUnitTest.java
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.download.dialogs;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TestRule;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.shadows.ShadowLog;
-
-import org.chromium.base.Callback;
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.JniMocker;
-import org.chromium.chrome.browser.download.DownloadDialogBridge;
-import org.chromium.chrome.browser.download.DownloadDialogBridgeJni;
-import org.chromium.chrome.browser.download.DownloadLaterPromptStatus;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper.Source;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.components.offline_items_collection.OfflineItemSchedule;
-import org.chromium.components.prefs.PrefService;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modelutil.PropertyModel;
-
-/**
- * Unit test for {@link DownloadLaterDialogHelper}.
- */
-@RunWith(BaseRobolectricTestRunner.class)
-public class DownloadLaterDialogHelperUnitTest {
-    private static final long START_TIME = 100;
-
-    @Mock
-    private DownloadLaterDialogCoordinator mDownloadLaterDialog;
-
-    @Mock
-    private Context mContext;
-
-    @Mock
-    private ModalDialogManager mModalDialogManager;
-
-    @Mock
-    private PrefService mPrefService;
-
-    @Mock
-    private Callback<OfflineItemSchedule> mMockCallback;
-
-    @Rule
-    public JniMocker mJniMocker = new JniMocker();
-
-    @Rule
-    public TestRule mCommandLineFlagsRule = CommandLineFlags.getTestRule();
-
-    @Mock
-    private DownloadDialogBridge.Natives mNativeMock;
-
-    private DownloadLaterDialogHelper mDownloadLaterDialogHelper;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        ShadowLog.stream = System.out;
-        mJniMocker.mock(DownloadDialogBridgeJni.TEST_HOOKS, mNativeMock);
-        when(mNativeMock.shouldShowDateTimePicker()).thenReturn(true);
-        when(mPrefService.getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS))
-                .thenReturn(DownloadLaterPromptStatus.SHOW_INITIAL);
-        doNothing().when(mPrefService).setInteger(anyString(), anyInt());
-
-        mDownloadLaterDialogHelper = new DownloadLaterDialogHelper(
-                mContext, mModalDialogManager, mPrefService, mDownloadLaterDialog);
-    }
-
-    @Test
-    public void testShowDialog() {
-        OfflineItemSchedule schedule = new OfflineItemSchedule(true, -1);
-        doAnswer(invocation -> {
-            mDownloadLaterDialogHelper.onDownloadLaterDialogComplete(
-                    DownloadLaterDialogChoice.DOWNLOAD_LATER, START_TIME);
-            return null;
-        })
-                .when(mDownloadLaterDialog)
-                .showDialog(any(), any(), any(), any());
-
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                schedule, Source.DOWNLOAD_HOME, mMockCallback);
-        verify(mDownloadLaterDialog, times(1)).showDialog(any(), any(), any(), any());
-        ArgumentCaptor<OfflineItemSchedule> captor =
-                ArgumentCaptor.forClass(OfflineItemSchedule.class);
-        verify(mMockCallback, times(1)).onResult(captor.capture());
-        Assert.assertEquals(START_TIME, captor.getValue().startTimeMs);
-        Assert.assertFalse(captor.getValue().onlyOnWifi);
-    }
-
-    @Test
-    public void testShowDialogWithScheduledStartTime() {
-        OfflineItemSchedule schedule = new OfflineItemSchedule(false, START_TIME);
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                schedule, Source.DOWNLOAD_HOME, mMockCallback);
-        ArgumentCaptor<PropertyModel> captor = ArgumentCaptor.forClass(PropertyModel.class);
-
-        verify(mDownloadLaterDialog, times(1)).showDialog(any(), any(), any(), captor.capture());
-        PropertyModel model = captor.getValue();
-        Assert.assertEquals(
-                START_TIME, (long) model.get(DownloadDateTimePickerDialogProperties.INITIAL_TIME));
-    }
-
-    @Test
-    public void testCancel() {
-        OfflineItemSchedule schedule = new OfflineItemSchedule(true, -1);
-        doAnswer(invocation -> {
-            mDownloadLaterDialogHelper.onDownloadLaterDialogCanceled();
-            return null;
-        })
-                .when(mDownloadLaterDialog)
-                .showDialog(any(), any(), any(), any());
-
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                schedule, Source.DOWNLOAD_INFOBAR, mMockCallback);
-        verify(mDownloadLaterDialog, times(1)).showDialog(any(), any(), any(), any());
-        verify(mMockCallback, times(1)).onResult(null);
-    }
-
-    @Test
-    public void testDestory() {
-        mDownloadLaterDialogHelper.destroy();
-        verify(mDownloadLaterDialog, times(1)).destroy();
-        verify(mMockCallback, times(0)).onResult(any());
-    }
-
-    @Test
-    @Features.EnableFeatures({ChromeFeatureList.DOWNLOAD_LATER})
-    @CommandLineFlags.Add({"enable-features=" + ChromeFeatureList.DOWNLOAD_LATER + "<FakeStudyName",
-            "force-fieldtrials=FakeStudyName/Enabled",
-            "force-fieldtrial-params=FakeStudyName.Enabled:show_date_time_picker/false"})
-    public void
-    testDownloadHideDownloadLaterDateTimePicker() {
-        when(mNativeMock.shouldShowDateTimePicker()).thenReturn(false);
-        OfflineItemSchedule schedule = new OfflineItemSchedule(false, START_TIME);
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                schedule, Source.DOWNLOAD_HOME, mMockCallback);
-        ArgumentCaptor<PropertyModel> captor = ArgumentCaptor.forClass(PropertyModel.class);
-        verify(mDownloadLaterDialog, times(1)).showDialog(any(), any(), any(), captor.capture());
-        PropertyModel model = captor.getValue();
-        Assert.assertFalse(model.get(DownloadLaterDialogProperties.SHOW_DATE_TIME_PICKER_OPTION));
-    }
-}
diff --git a/chrome/browser/download/download_offline_content_provider.cc b/chrome/browser/download/download_offline_content_provider.cc
index 0b67cf0..dcc96ad 100644
--- a/chrome/browser/download/download_offline_content_provider.cc
+++ b/chrome/browser/download/download_offline_content_provider.cc
@@ -38,7 +38,6 @@
 using OfflineItemState = offline_items_collection::OfflineItemState;
 using OfflineItemProgressUnit =
     offline_items_collection::OfflineItemProgressUnit;
-using offline_items_collection::OfflineItemSchedule;
 using offline_items_collection::OfflineItemShareInfo;
 using OfflineItemVisuals = offline_items_collection::OfflineItemVisuals;
 using UpdateDelta = offline_items_collection::UpdateDelta;
@@ -392,25 +391,6 @@
   item->Rename(base::FilePath(filename), std::move(download_callback));
 }
 
-void DownloadOfflineContentProvider::ChangeSchedule(
-    const ContentId& id,
-    absl::optional<OfflineItemSchedule> schedule) {
-  EnsureDownloadCoreServiceStarted();
-  if (state_ != State::HISTORY_LOADED) {
-    pending_actions_for_full_browser_.push_back(base::BindOnce(
-        &DownloadOfflineContentProvider::ChangeSchedule,
-        weak_ptr_factory_.GetWeakPtr(), id, std::move(schedule)));
-    return;
-  }
-
-  DownloadItem* item = GetDownload(id.id);
-  if (!item)
-    return;
-
-  item->OnDownloadScheduleChanged(
-      OfflineItemUtils::ToDownloadSchedule(schedule));
-}
-
 void DownloadOfflineContentProvider::OnRenameDownloadCallbackDone(
     RenameCallback callback,
     DownloadItem* item,
diff --git a/chrome/browser/download/download_offline_content_provider.h b/chrome/browser/download/download_offline_content_provider.h
index b4a9c75b..621d7524 100644
--- a/chrome/browser/download/download_offline_content_provider.h
+++ b/chrome/browser/download/download_offline_content_provider.h
@@ -82,10 +82,6 @@
   void RenameItem(const ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(
-      const offline_items_collection::ContentId& id,
-      absl::optional<offline_items_collection::OfflineItemSchedule> schedule)
-      override;
 
   // Methods that can be run in reduced mode.
   void CancelDownload(const ContentId& id) override;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
index 4363060..794fb077 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/DownloadMessageUiControllerImpl.java
@@ -23,13 +23,9 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.browser.download.DownloadLaterMetrics.DownloadLaterUiEvent;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper.Source;
 import org.chromium.chrome.browser.download.internal.R;
 import org.chromium.chrome.browser.download.items.OfflineContentAggregatorFactory;
 import org.chromium.chrome.browser.profiles.OTRProfileID;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.components.browser_ui.util.date.CalendarUtils;
 import org.chromium.components.messages.DismissReason;
 import org.chromium.components.messages.MessageBannerProperties;
@@ -43,10 +39,8 @@
 import org.chromium.components.offline_items_collection.OfflineItemSchedule;
 import org.chromium.components.offline_items_collection.OfflineItemState;
 import org.chromium.components.offline_items_collection.UpdateDelta;
-import org.chromium.components.prefs.PrefService;
 import org.chromium.components.url_formatter.SchemeDisplay;
 import org.chromium.components.url_formatter.UrlFormatter;
-import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.url.GURL;
@@ -319,9 +313,6 @@
     // Represents the currently displayed UI data.
     private DownloadProgressMessageUiData mCurrentInfo;
 
-    // Used to show the download later dialog to change download schedule.
-    private DownloadLaterDialogHelper mDownloadLaterDialogHelper;
-
     // The delegate to provide dependencies.
     private final Delegate mDelegate;
 
@@ -965,9 +956,7 @@
             ContentId itemId, final OfflineItemSchedule schedule) {
         OfflineItem offlineItem = mTrackedItems.remove(itemId);
         removeNotification(itemId);
-        if (itemId != null && schedule != null) {
-            onChangeScheduleClicked(itemId, schedule);
-        } else if (itemId != null) {
+        if (itemId != null) {
             mDelegate.openDownload(itemId,
                     OTRProfileID.deserializeWithoutVerify(
                             offlineItem == null ? null : offlineItem.otrProfileId),
@@ -1000,23 +989,6 @@
         }
     }
 
-    private void onChangeScheduleClicked(
-            final ContentId id, final OfflineItemSchedule currentSchedule) {
-        if (mDownloadLaterDialogHelper != null) mDownloadLaterDialogHelper.destroy();
-
-        PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
-        // Show the download later dialog to let the user change download schedule.
-        mDownloadLaterDialogHelper = DownloadLaterDialogHelper.create(
-                getContext(), getModalDialogManager(), prefService);
-        DownloadLaterMetrics.recordDownloadLaterUiEvent(
-                DownloadLaterUiEvent.DOWNLOAD_INFOBAR_CHANGE_SCHEDULE_CLICKED);
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                currentSchedule, Source.DOWNLOAD_INFOBAR, (newSchedule) -> {
-                    if (newSchedule == null) return;
-                    OfflineContentAggregatorFactory.get().changeSchedule(id, newSchedule);
-                });
-    }
-
     private static void recordMessageState(@UiState int state, DownloadProgressMessageUiData info) {
         int shownState = -1;
         int multipleDownloadState = -1;
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
index 321c7c46..f973c67 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadActivityV2Test.java
@@ -20,10 +20,8 @@
 import static org.hamcrest.Matchers.equalToIgnoringCase;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.core.AllOf.allOf;
-import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
@@ -54,14 +52,12 @@
 import org.chromium.base.task.PostTask;
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.download.DownloadLaterPromptStatus;
 import org.chromium.chrome.browser.download.home.list.ListUtils;
 import org.chromium.chrome.browser.download.home.list.holder.ListItemViewHolder;
 import org.chromium.chrome.browser.download.home.rename.RenameUtils;
 import org.chromium.chrome.browser.download.home.toolbar.DownloadHomeToolbar;
 import org.chromium.chrome.browser.download.internal.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
@@ -73,7 +69,6 @@
 import org.chromium.components.offline_items_collection.OfflineItemFilter;
 import org.chromium.components.offline_items_collection.OfflineItemState;
 import org.chromium.components.offline_items_collection.RenameResult;
-import org.chromium.components.prefs.PrefService;
 import org.chromium.components.url_formatter.SchemeDisplay;
 import org.chromium.components.url_formatter.UrlFormatter;
 import org.chromium.components.url_formatter.UrlFormatterJni;
@@ -105,9 +100,6 @@
     @Mock
     private UrlFormatter.Natives mUrlFormatterJniMock;
 
-    @Mock
-    PrefService mPrefService;
-
     private ModalDialogManager.Presenter mAppModalPresenter;
 
     private ModalDialogManager mModalDialogManager;
@@ -147,9 +139,6 @@
         when(mUrlFormatterJniMock.formatStringUrlForSecurityDisplay(
                      anyString(), eq(SchemeDisplay.OMIT_HTTP_AND_HTTPS)))
                 .then(inv -> inv.getArgument(0));
-        when(mPrefService.getInteger(eq(Pref.DOWNLOAD_LATER_PROMPT_STATUS)))
-                .thenReturn(DownloadLaterPromptStatus.SHOW_INITIAL);
-        doNothing().when(mPrefService).setInteger(anyString(), anyInt());
 
         Map<String, Boolean> features = new HashMap<>();
         features.put(ChromeFeatureList.OFFLINE_PAGES_PREFETCHING, true);
@@ -197,10 +186,10 @@
         ObservableSupplierImpl<Boolean> isPrefetchEnabledSupplier = new ObservableSupplierImpl<>();
         isPrefetchEnabledSupplier.set(true);
 
-        mDownloadCoordinator = new DownloadManagerCoordinatorImpl(getActivity(), config,
-                isPrefetchEnabledSupplier, settingsLauncher, mSnackbarManager, mModalDialogManager,
-                mPrefService, mTracker, faviconProvider, mStubbedOfflineContentProvider,
-                mDiscardableReferencePool);
+        mDownloadCoordinator =
+                new DownloadManagerCoordinatorImpl(getActivity(), config, isPrefetchEnabledSupplier,
+                        settingsLauncher, mSnackbarManager, mModalDialogManager, mTracker,
+                        faviconProvider, mStubbedOfflineContentProvider, mDiscardableReferencePool);
         getActivity().setContentView(mDownloadCoordinator.getView());
 
         mDownloadCoordinator.updateForUrl(UrlConstants.DOWNLOADS_URL);
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
index 1c9f510..b9ba8cff 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactory.java
@@ -13,7 +13,6 @@
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
-import org.chromium.components.prefs.PrefService;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
 /** Factory class to build a DownloadManagerCoordinator instance. */
@@ -24,12 +23,10 @@
     public static DownloadManagerCoordinator create(Activity activity,
             DownloadManagerUiConfig config, Supplier<Boolean> exploreOfflineTabVisibilitySupplier,
             Callback<Context> settingsLauncher, SnackbarManager snackbarManager,
-            ModalDialogManager modalDialogManager, PrefService prefService, Tracker tracker,
-            FaviconProvider faviconProvider, OfflineContentProvider provider,
-            DiscardableReferencePool discardableReferencePool) {
+            ModalDialogManager modalDialogManager, Tracker tracker, FaviconProvider faviconProvider,
+            OfflineContentProvider provider, DiscardableReferencePool discardableReferencePool) {
         return new DownloadManagerCoordinatorImpl(activity, config,
                 exploreOfflineTabVisibilitySupplier, settingsLauncher, snackbarManager,
-                modalDialogManager, prefService, tracker, faviconProvider, provider,
-                discardableReferencePool);
+                modalDialogManager, tracker, faviconProvider, provider, discardableReferencePool);
     }
 }
\ No newline at end of file
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
index c203a27a..5f3a881 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -30,7 +30,6 @@
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
-import org.chromium.components.prefs.PrefService;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
@@ -60,9 +59,8 @@
     public DownloadManagerCoordinatorImpl(Activity activity, DownloadManagerUiConfig config,
             Supplier<Boolean> exploreOfflineTabVisibilitySupplier,
             Callback<Context> settingsLauncher, SnackbarManager snackbarManager,
-            ModalDialogManager modalDialogManager, PrefService prefService, Tracker tracker,
-            FaviconProvider faviconProvider, OfflineContentProvider provider,
-            DiscardableReferencePool discardableReferencePool) {
+            ModalDialogManager modalDialogManager, Tracker tracker, FaviconProvider faviconProvider,
+            OfflineContentProvider provider, DiscardableReferencePool discardableReferencePool) {
         mActivity = activity;
         mSettingsLauncher = settingsLauncher;
         mDeleteCoordinator = new DeleteUndoCoordinator(snackbarManager);
@@ -70,7 +68,7 @@
         mListCoordinator = new DateOrderedListCoordinator(mActivity, config,
                 exploreOfflineTabVisibilitySupplier, provider, mDeleteCoordinator::showSnackbar,
                 mSelectionDelegate, this::notifyFilterChanged, createDateOrderedListObserver(),
-                modalDialogManager, prefService, faviconProvider, discardableReferencePool);
+                modalDialogManager, faviconProvider, discardableReferencePool);
         mToolbarCoordinator = new ToolbarCoordinator(mActivity, this, mListCoordinator,
                 mSelectionDelegate, config.isSeparateActivity, tracker);
 
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedOfflineContentProvider.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedOfflineContentProvider.java
index 6d75f27..735bbb1 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedOfflineContentProvider.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedOfflineContentProvider.java
@@ -15,7 +15,6 @@
 import org.chromium.components.offline_items_collection.ContentId;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
-import org.chromium.components.offline_items_collection.OfflineItemSchedule;
 import org.chromium.components.offline_items_collection.OpenParams;
 import org.chromium.components.offline_items_collection.RenameResult;
 import org.chromium.components.offline_items_collection.ShareCallback;
@@ -109,9 +108,6 @@
     public void resumeDownload(ContentId id, boolean hasUserGesture) {}
 
     @Override
-    public void changeSchedule(final ContentId id, final OfflineItemSchedule schedule) {}
-
-    @Override
     public void cancelDownload(ContentId id) {}
 
     @Override
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedProvider.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedProvider.java
index 03458b8..298b4279 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedProvider.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/StubbedProvider.java
@@ -16,7 +16,6 @@
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
 import org.chromium.components.offline_items_collection.OfflineItemFilter;
-import org.chromium.components.offline_items_collection.OfflineItemSchedule;
 import org.chromium.components.offline_items_collection.OfflineItemState;
 import org.chromium.components.offline_items_collection.OpenParams;
 import org.chromium.components.offline_items_collection.RenameResult;
@@ -84,9 +83,6 @@
         public void resumeDownload(ContentId id, boolean hasUserGesture) {}
 
         @Override
-        public void changeSchedule(final ContentId id, final OfflineItemSchedule schedule) {}
-
-        @Override
         public void cancelDownload(ContentId id) {}
 
         @Override
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
index 1693998..fd037737 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListCoordinator.java
@@ -16,7 +16,6 @@
 import org.chromium.base.DiscardableReferencePool;
 import org.chromium.base.Log;
 import org.chromium.base.supplier.Supplier;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
 import org.chromium.chrome.browser.download.home.FaviconProvider;
 import org.chromium.chrome.browser.download.home.StableIds;
@@ -32,7 +31,6 @@
 import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
 import org.chromium.components.offline_items_collection.OfflineContentProvider;
 import org.chromium.components.offline_items_collection.OfflineItem;
-import org.chromium.components.prefs.PrefService;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
 import java.util.List;
@@ -105,7 +103,6 @@
      *                                  components that need to take action based on the visual
      *                                  state of the list.
      * @param dateOrderedListObserver   A {@link DateOrderedListObserver}.
-     * @param prefService               Used to update user preferences.
      * @param discardableReferencePool  A {@linK DiscardableReferencePool} reference to use for
      *                                  large objects (e.g. bitmaps) in the UI.
      */
@@ -114,8 +111,7 @@
             DeleteController deleteController, SelectionDelegate<ListItem> selectionDelegate,
             FilterCoordinator.Observer filterObserver,
             DateOrderedListObserver dateOrderedListObserver, ModalDialogManager modalDialogManager,
-            PrefService prefService, FaviconProvider faviconProvider,
-            DiscardableReferencePool discardableReferencePool) {
+            FaviconProvider faviconProvider, DiscardableReferencePool discardableReferencePool) {
         mContext = context;
 
         ListItemModel model = new ListItemModel();
@@ -124,8 +120,7 @@
                 new DateOrderedListView(context, config, decoratedModel, dateOrderedListObserver);
         mRenameDialogManager = new RenameDialogManager(context, modalDialogManager);
         mMediator = new DateOrderedListMediator(provider, faviconProvider, this::startShareIntent,
-                deleteController, this::startRename, selectionDelegate,
-                DownloadLaterDialogHelper.create(context, modalDialogManager, prefService), config,
+                deleteController, this::startRename, selectionDelegate, config,
                 dateOrderedListObserver, model, discardableReferencePool);
 
         mEmptyCoordinator = new EmptyCoordinator(context, mMediator.getEmptySource());
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
index 12dcbe39..969bf0a 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/DateOrderedListMediator.java
@@ -14,10 +14,6 @@
 import org.chromium.base.Callback;
 import org.chromium.base.CollectionUtil;
 import org.chromium.base.DiscardableReferencePool;
-import org.chromium.chrome.browser.download.DownloadLaterMetrics;
-import org.chromium.chrome.browser.download.DownloadLaterMetrics.DownloadLaterUiEvent;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper;
-import org.chromium.chrome.browser.download.dialogs.DownloadLaterDialogHelper.Source;
 import org.chromium.chrome.browser.download.home.DownloadManagerUiConfig;
 import org.chromium.chrome.browser.download.home.FaviconProvider;
 import org.chromium.chrome.browser.download.home.JustNowProvider;
@@ -113,7 +109,6 @@
     private final MediatorSelectionObserver mSelectionObserver;
     private final SelectionDelegate<ListItem> mSelectionDelegate;
     private final DownloadManagerUiConfig mUiConfig;
-    private final DownloadLaterDialogHelper mDownloadLaterDialogHelper;
 
     private final OffTheRecordOfflineItemFilter mOffTheRecordFilter;
     private final InvalidStateOfflineItemFilter mInvalidStateFilter;
@@ -167,9 +162,8 @@
     public DateOrderedListMediator(OfflineContentProvider provider, FaviconProvider faviconProvider,
             ShareController shareController, DeleteController deleteController,
             RenameController renameController, SelectionDelegate<ListItem> selectionDelegate,
-            DownloadLaterDialogHelper downloadLaterDialogHelper, DownloadManagerUiConfig config,
-            DateOrderedListObserver dateOrderedListObserver, ListItemModel model,
-            DiscardableReferencePool discardableReferencePool) {
+            DownloadManagerUiConfig config, DateOrderedListObserver dateOrderedListObserver,
+            ListItemModel model, DiscardableReferencePool discardableReferencePool) {
         // Build a chain from the data source to the model.  The chain will look like:
         // [OfflineContentProvider] ->
         //     [OfflineItemSource] ->
@@ -190,7 +184,6 @@
         mDeleteController = deleteController;
         mRenameController = renameController;
         mSelectionDelegate = selectionDelegate;
-        mDownloadLaterDialogHelper = downloadLaterDialogHelper;
         mUiConfig = config;
 
         mSource = new OfflineItemSource(mProvider);
@@ -225,7 +218,6 @@
         mModel.getProperties().set(ListProperties.PROVIDER_FAVICON, this::getFavicon);
         mModel.getProperties().set(ListProperties.CALLBACK_SELECTION, this::onSelection);
         mModel.getProperties().set(ListProperties.CALLBACK_RENAME, this::onRenameItem);
-        mModel.getProperties().set(ListProperties.CALLBACK_CHANGE, this::onChangeItem);
         mModel.getProperties().set(
                 ListProperties.CALLBACK_PAGINATION_CLICK, mListMutationController::loadMorePages);
         mModel.getProperties().set(ListProperties.CALLBACK_GROUP_PAGINATION_CLICK,
@@ -236,7 +228,6 @@
     public void destroy() {
         mSource.destroy();
         mThumbnailProvider.destroy();
-        mDownloadLaterDialogHelper.destroy();
     }
 
     /**
@@ -350,17 +341,6 @@
         });
     }
 
-    private void onChangeItem(OfflineItem item) {
-        UmaUtils.recordItemAction(ViewAction.MENU_CHANGE);
-        DownloadLaterMetrics.recordDownloadLaterUiEvent(
-                DownloadLaterUiEvent.DOWNLOAD_HOME_CHANGE_SCHEDULE_CLICKED);
-        mDownloadLaterDialogHelper.showChangeScheduleDialog(
-                item.schedule, Source.DOWNLOAD_HOME, (newSchedule) -> {
-                    if (newSchedule == null) return;
-                    mProvider.changeSchedule(item.id, newSchedule);
-                });
-    }
-
     /**
      * Deletes a given list of items. If the items are not completed yet, they would be cancelled.
      * @param items The list of items to delete.
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
index a4b864d..15c4771e 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListProperties.java
@@ -79,10 +79,6 @@
     WritableObjectPropertyKey<Callback<OfflineItem>> CALLBACK_RENAME =
             new WritableObjectPropertyKey<>();
 
-    /** The callback for when a UI action should change the {@link OfflineItem}. */
-    WritableObjectPropertyKey<Callback<OfflineItem>> CALLBACK_CHANGE =
-            new WritableObjectPropertyKey<>();
-
     /** The provider to retrieve expensive assets for a {@link OfflineItem}. */
     WritableObjectPropertyKey<VisualsProvider> PROVIDER_VISUALS = new WritableObjectPropertyKey<>();
 
@@ -106,7 +102,6 @@
 
     PropertyKey[] ALL_KEYS = new PropertyKey[] {ENABLE_ITEM_ANIMATIONS, CALLBACK_OPEN,
             CALLBACK_PAUSE, CALLBACK_RESUME, CALLBACK_CANCEL, CALLBACK_SHARE, CALLBACK_REMOVE,
-            CALLBACK_RENAME, CALLBACK_CHANGE, PROVIDER_VISUALS, PROVIDER_FAVICON,
-            CALLBACK_SELECTION, SELECTION_MODE_ACTIVE, CALLBACK_PAGINATION_CLICK,
-            CALLBACK_GROUP_PAGINATION_CLICK};
+            CALLBACK_RENAME, PROVIDER_VISUALS, PROVIDER_FAVICON, CALLBACK_SELECTION,
+            SELECTION_MODE_ACTIVE, CALLBACK_PAGINATION_CLICK, CALLBACK_GROUP_PAGINATION_CLICK};
 }
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
index cd38bee..cb60d96e 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/ListPropertyViewBinder.java
@@ -36,7 +36,6 @@
                 || propertyKey == ListProperties.PROVIDER_VISUALS
                 || propertyKey == ListProperties.CALLBACK_SELECTION
                 || propertyKey == ListProperties.CALLBACK_RENAME
-                || propertyKey == ListProperties.CALLBACK_CHANGE
                 || propertyKey == ListProperties.SELECTION_MODE_ACTIVE) {
             view.getAdapter().notifyItemRangeChanged(0, view.getAdapter().getItemCount());
         }
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
index 226c5c4..e45ca85 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
@@ -48,7 +48,6 @@
     private Runnable mShareCallback;
     private Runnable mDeleteCallback;
     private Runnable mRenameCallback;
-    private Runnable mChangeCallback;
 
     // flag to hide rename list menu option for offline pages
     private boolean mCanRename;
@@ -144,11 +143,6 @@
         mDeleteCallback =
                 () -> properties.get(ListProperties.CALLBACK_REMOVE).onResult(offlineItem);
 
-        if (mIsScheduled) {
-            mChangeCallback =
-                    () -> properties.get(ListProperties.CALLBACK_CHANGE).onResult(offlineItem);
-        }
-
         mMore.setClickable(!properties.get(ListProperties.SELECTION_MODE_ACTIVE));
     }
 
@@ -165,7 +159,6 @@
 
         if (mCanShare) listItems.add(buildMenuListItem(R.string.share, 0, 0));
         if (mCanRename) listItems.add(buildMenuListItem(R.string.rename, 0, 0));
-        if (mIsScheduled) listItems.add(buildMenuListItem(R.string.change, 0, 0));
 
         listItems.add(buildMenuListItem(R.string.delete, 0, 0));
         ListMenu.Delegate delegate = (model) -> {
@@ -176,8 +169,6 @@
                 if (mDeleteCallback != null) mDeleteCallback.run();
             } else if (textId == R.string.rename) {
                 if (mRenameCallback != null) mRenameCallback.run();
-            } else if (textId == R.string.change) {
-                if (mChangeCallback != null) mChangeCallback.run();
             }
         };
         return new BasicListMenu(mMore.getContext(), listItems, delegate);
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java
index b4af687b..7cc5507 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/interstitial/DownloadInterstitialProperties.java
@@ -57,10 +57,9 @@
 
     PropertyKey[] ALL_KEYS = new PropertyKey[] {ENABLE_ITEM_ANIMATIONS, CALLBACK_OPEN,
             CALLBACK_PAUSE, CALLBACK_RESUME, CALLBACK_CANCEL, CALLBACK_SHARE, CALLBACK_REMOVE,
-            CALLBACK_RENAME, CALLBACK_CHANGE, PROVIDER_VISUALS, PROVIDER_FAVICON,
-            CALLBACK_SELECTION, SELECTION_MODE_ACTIVE, CALLBACK_PAGINATION_CLICK,
-            CALLBACK_GROUP_PAGINATION_CLICK, DOWNLOAD_ITEM, STATE, TITLE_TEXT,
-            PRIMARY_BUTTON_IS_VISIBLE, PRIMARY_BUTTON_TEXT, PRIMARY_BUTTON_CALLBACK,
-            SECONDARY_BUTTON_IS_VISIBLE, SECONDARY_BUTTON_TEXT, SECONDARY_BUTTON_CALLBACK,
-            SHOULD_REMOVE_PENDING_MESSAGE};
+            CALLBACK_RENAME, PROVIDER_VISUALS, PROVIDER_FAVICON, CALLBACK_SELECTION,
+            SELECTION_MODE_ACTIVE, CALLBACK_PAGINATION_CLICK, CALLBACK_GROUP_PAGINATION_CLICK,
+            DOWNLOAD_ITEM, STATE, TITLE_TEXT, PRIMARY_BUTTON_IS_VISIBLE, PRIMARY_BUTTON_TEXT,
+            PRIMARY_BUTTON_CALLBACK, SECONDARY_BUTTON_IS_VISIBLE, SECONDARY_BUTTON_TEXT,
+            SECONDARY_BUTTON_CALLBACK, SHOULD_REMOVE_PENDING_MESSAGE};
 }
diff --git a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
index 96ced8a..7cee4fe 100644
--- a/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
+++ b/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api_unittest.cc
@@ -151,10 +151,10 @@
   ASSERT_TRUE(GetAppIdHashInEnterpriseContext(rp_id_hash, &result));
   EXPECT_FALSE(result);
 
-  base::Value::ListStorage permitted_list;
-  permitted_list.emplace_back(example_com);
-  profile()->GetPrefs()->Set(prefs::kSecurityKeyPermitAttestation,
-                             base::Value(permitted_list));
+  base::Value::List permitted_list;
+  permitted_list.Append(example_com);
+  profile()->GetPrefs()->SetList(prefs::kSecurityKeyPermitAttestation,
+                                 std::move(permitted_list));
 
   ASSERT_TRUE(GetAppIdHashInEnterpriseContext(example_com_hash, &result));
   EXPECT_TRUE(result);
@@ -350,10 +350,10 @@
 
 TEST_F(CryptoTokenPermissionTest, PolicyOverridesAttestationPrompt) {
   const std::string example_com("https://example.com");
-  base::Value::ListStorage permitted_list;
-  permitted_list.emplace_back(example_com);
-  profile()->GetPrefs()->Set(prefs::kSecurityKeyPermitAttestation,
-                             base::Value(permitted_list));
+  base::Value::List permitted_list;
+  permitted_list.Append(example_com);
+  profile()->GetPrefs()->SetList(prefs::kSecurityKeyPermitAttestation,
+                                 std::move(permitted_list));
 
   // If an appId is configured by enterprise policy then attestation requests
   // should be permitted without showing a prompt.
diff --git a/chrome/browser/extensions/api/idltest/idltest_api.cc b/chrome/browser/extensions/api/idltest/idltest_api.cc
index b54ad53..3ef76a3 100644
--- a/chrome/browser/extensions/api/idltest/idltest_api.cc
+++ b/chrome/browser/extensions/api/idltest/idltest_api.cc
@@ -17,10 +17,10 @@
 
 base::Value CopyBinaryValueToIntegerList(
     const base::Value::BlobStorage& input) {
-  base::Value::ListStorage list;
+  base::Value::List list;
   list.reserve(input.size());
   for (int c : input)
-    list.emplace_back(c);
+    list.Append(c);
   return base::Value(std::move(list));
 }
 
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 145bf44c..1515166 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -534,9 +534,8 @@
 
 // Test that the webRequest events are dispatched with the expected details when
 // a frame or tab is removed while a response is being received.
-// Flaky: https://crbug.com/617865
 IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
-                       DISABLED_WebRequestUnloadAfterRequest) {
+                       WebRequestUnloadAfterRequest) {
   ASSERT_TRUE(StartEmbeddedTestServer());
   ASSERT_TRUE(
       RunExtensionTest("webrequest", {.page_url = "test_unload.html?1"}))
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index 84790e3..5d314d2 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -453,6 +453,7 @@
     case mojom::ViewType::kExtensionBackgroundPage:
     case mojom::ViewType::kExtensionDialog:
     case mojom::ViewType::kExtensionPopup:
+    case mojom::ViewType::kOffscreenDocument:
       // These are the only types that are tracked by the ExtensionTag.
       task_manager::WebContentsTags::CreateForExtension(web_contents,
                                                         view_type);
diff --git a/chrome/browser/extensions/offscreen_document_browsertest.cc b/chrome/browser/extensions/offscreen_document_browsertest.cc
new file mode 100644
index 0000000..e8ef02d
--- /dev/null
+++ b/chrome/browser/extensions/offscreen_document_browsertest.cc
@@ -0,0 +1,311 @@
+// 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 "extensions/browser/offscreen_document_host.h"
+
+#include "base/test/scoped_feature_list.h"
+#include "base/test/values_test_util.h"
+#include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "extensions/browser/background_script_executor.h"
+#include "extensions/browser/process_manager.h"
+#include "extensions/browser/process_map.h"
+#include "extensions/browser/script_result_queue.h"
+#include "extensions/browser/view_type_utils.h"
+#include "extensions/common/extension_features.h"
+#include "extensions/common/features/feature.h"
+#include "extensions/test/test_extension_dir.h"
+
+namespace extensions {
+
+class OffscreenDocumentBrowserTest : public ExtensionApiTest {
+ public:
+  OffscreenDocumentBrowserTest() {
+    feature_list_.InitAndEnableFeature(
+        extensions_features::kExtensionsOffscreenDocuments);
+  }
+  ~OffscreenDocumentBrowserTest() override = default;
+
+  // Creates a new OffscreenDocumentHost and waits for it to load.
+  std::unique_ptr<OffscreenDocumentHost> CreateOffscreenDocument(
+      const Extension& extension,
+      const GURL& url) {
+    scoped_refptr<content::SiteInstance> site_instance =
+        ProcessManager::Get(profile())->GetSiteInstanceForURL(url);
+
+    content::TestNavigationObserver navigation_observer(url);
+    navigation_observer.StartWatchingNewWebContents();
+    auto offscreen_document = std::make_unique<OffscreenDocumentHost>(
+        extension, site_instance.get(), url);
+    offscreen_document->CreateRendererSoon();
+    navigation_observer.Wait();
+    EXPECT_TRUE(navigation_observer.last_navigation_succeeded());
+
+    return offscreen_document;
+  }
+
+  // Executes a script in `web_contents` and extracts a string from the
+  // result.
+  std::string ExecuteScriptSync(content::WebContents* web_contents,
+                                const std::string& script) {
+    std::string result;
+    EXPECT_TRUE(
+        content::ExecuteScriptAndExtractString(web_contents, script, &result))
+        << script;
+    return result;
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+// Test basic properties of offscreen documents.
+IN_PROC_BROWSER_TEST_F(OffscreenDocumentBrowserTest,
+                       CreateBasicOffscreenDocument) {
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Offscreen Document Test",
+           "manifest_version": 3,
+           "version": "0.1"
+         })";
+  static constexpr char kOffscreenDocumentHtml[] =
+      R"(<html>
+           <body>
+             <div id="signal">Hello, World</div>
+           </body>
+         </html>)";
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(FILE_PATH_LITERAL("offscreen.html"),
+                     kOffscreenDocumentHtml);
+  test_dir.WriteFile(FILE_PATH_LITERAL("other.html"), "<html>Empty</html>");
+
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+
+  const GURL offscreen_url = extension->GetResourceURL("offscreen.html");
+  ProcessManager* const process_manager = ProcessManager::Get(profile());
+
+  std::unique_ptr<OffscreenDocumentHost> offscreen_document =
+      CreateOffscreenDocument(*extension, offscreen_url);
+
+  // Check basic properties:
+  content::WebContents* contents = offscreen_document->host_contents();
+  ASSERT_TRUE(contents);
+  // - The URL should match the extension's URL.
+  EXPECT_EQ(offscreen_url, contents->GetLastCommittedURL());
+  // - The offscreen document should be, well, offscreen; it should not be
+  //   contained within any Browser window.
+  EXPECT_EQ(nullptr, chrome::FindBrowserWithWebContents(contents));
+  // - The view type should be correctly set (it should not be considered a
+  //   background page, tab, or other type of view).
+  EXPECT_EQ(mojom::ViewType::kOffscreenDocument,
+            offscreen_document->extension_host_type());
+  EXPECT_EQ(mojom::ViewType::kOffscreenDocument, GetViewType(contents));
+
+  {
+    // Check the registration in the ProcessManager: the offscreen document
+    // should be associated with the extension and have a registered frame.
+    ProcessManager::FrameSet frames_for_extension =
+        process_manager->GetRenderFrameHostsForExtension(extension->id());
+    ASSERT_EQ(1u, frames_for_extension.size());
+    content::RenderFrameHost* frame_host = *frames_for_extension.begin();
+    EXPECT_EQ(offscreen_url, frame_host->GetLastCommittedURL());
+    EXPECT_EQ(contents, content::WebContents::FromRenderFrameHost(frame_host));
+    EXPECT_EQ(extension, process_manager->GetExtensionForWebContents(contents));
+  }
+
+  {
+    Feature::Context context_type =
+        ProcessMap::Get(profile())->GetMostLikelyContextType(
+            extension, contents->GetPrimaryMainFrame()->GetProcess()->GetID(),
+            &offscreen_url);
+    // TODO(https://crbug.com/1339382): The following check should be:
+    //   EXPECT_EQ(Feature::OFFSCREEN_EXTENSION_CONTEXT, context_type);
+    // However, currently the ProcessMap can't differentiate between a
+    // blessed extension context and an offscreen document, as both run in the
+    // primary extension process and have committed to the extension origin.
+    // This is okay (this boundary isn't a security boundary), but is
+    // technically incorrect.
+    // See also comment in ProcessMap::GetMostLikelyContextType().
+    EXPECT_EQ(Feature::BLESSED_EXTENSION_CONTEXT, context_type);
+  }
+
+  {
+    // Check the document loaded properly (and, implicitly check that it does,
+    // in fact, have a DOM).
+    static constexpr char kScript[] =
+        R"({
+             let div = document.getElementById('signal');
+             domAutomationController.send(div ? div.innerText : '<no div>');
+           })";
+    EXPECT_EQ("Hello, World", ExecuteScriptSync(contents, kScript));
+  }
+
+  {
+    // Check that the offscreen document runs in the same process as other
+    // extension frames. Do this by comparing it to another extension page in
+    // a tab.
+    ASSERT_TRUE(ui_test_utils::NavigateToURL(
+        browser(), extension->GetResourceURL("other.html")));
+    content::WebContents* tab_contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    EXPECT_EQ(tab_contents->GetPrimaryMainFrame()->GetProcess(),
+              contents->GetPrimaryMainFrame()->GetProcess());
+  }
+}
+
+// Tests that extension API access in offscreen documents is extremely limited.
+IN_PROC_BROWSER_TEST_F(OffscreenDocumentBrowserTest, APIAccessIsLimited) {
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Offscreen Document Test",
+           "manifest_version": 3,
+           "version": "0.1",
+           "permissions": ["storage", "tabs"]
+         })";
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(FILE_PATH_LITERAL("offscreen.html"),
+                     "<html>Offscreen</html>");
+
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+  const GURL offscreen_url = extension->GetResourceURL("offscreen.html");
+
+  std::unique_ptr<OffscreenDocumentHost> offscreen_document =
+      CreateOffscreenDocument(*extension, offscreen_url);
+  content::WebContents* contents = offscreen_document->host_contents();
+
+  {
+    // Offscreen documents have very limited API access. Even though the
+    // extension has the storage and tabs permissions, the only extension API
+    // exposed should be `runtime` (and our test API).
+    constexpr char kScript[] =
+        R"({
+             let keys = Object.keys(chrome);
+             domAutomationController.send(JSON.stringify(keys.sort()));
+           })";
+    EXPECT_EQ(R"(["csi","loadTimes","runtime","test"])",
+              ExecuteScriptSync(contents, kScript));
+  }
+
+  {
+    // Even runtime should be fairly restricted. Enums are always exposed, and
+    // offscreen documents have access to message passing capabilities and their
+    // own extension ID and URL. Intentionally absent are methods like
+    // `runtime.getViews()`.
+    constexpr char kScript[] =
+        R"({
+             let keys = Object.keys(chrome.runtime);
+             domAutomationController.send(JSON.stringify(keys.sort()));
+           })";
+    static constexpr char kExpectedProperties[] =
+        R"(["OnInstalledReason","OnRestartRequiredReason","PlatformArch",)"
+        R"("PlatformNaclArch","PlatformOs","RequestUpdateCheckStatus",)"
+        R"("connect","getURL","id","onConnect","onMessage","sendMessage"])";
+    EXPECT_EQ(kExpectedProperties, ExecuteScriptSync(contents, kScript));
+  }
+}
+
+// Exercise message passing between the offscreen document and a corresponding
+// service worker.
+IN_PROC_BROWSER_TEST_F(OffscreenDocumentBrowserTest, MessagingTest) {
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Offscreen Document Test",
+           "manifest_version": 3,
+           "version": "0.1",
+           "background": { "service_worker": "background.js" }
+         })";
+  static constexpr char kOffscreenDocumentHtml[] =
+      R"(<html>
+           Offscreen
+           <script src="offscreen.js"></script>
+         </html>)";
+  // Both the offscreen document and the service worker have methods to send a
+  // message and to echo back arguments with a reply.
+  static constexpr char kOffscreenDocumentJs[] =
+      R"(chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
+           sendResponse({msg, sender, reply: 'offscreen reply'});
+         });
+         function sendMessageFromOffscreen() {
+           chrome.runtime.sendMessage('message from offscreen', (response) => {
+             chrome.test.sendScriptResult(response);
+           });
+         })";
+  static constexpr char kBackgroundJs[] =
+      R"(chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
+           sendResponse({msg, sender, reply: 'background reply'});
+         });
+         function sendMessageFromBackground() {
+           chrome.runtime.sendMessage('message from background', (response) => {
+             chrome.test.sendScriptResult(response);
+           });
+         })";
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(FILE_PATH_LITERAL("offscreen.html"),
+                     kOffscreenDocumentHtml);
+  test_dir.WriteFile(FILE_PATH_LITERAL("offscreen.js"), kOffscreenDocumentJs);
+  test_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
+
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+
+  const GURL offscreen_url = extension->GetResourceURL("offscreen.html");
+
+  std::unique_ptr<OffscreenDocumentHost> offscreen_document =
+      CreateOffscreenDocument(*extension, offscreen_url);
+
+  {
+    // First, try sending a message from the service worker to the offscreen
+    // document.
+    std::string expected = content::JsReplace(
+        R"({
+             "msg": "message from background",
+             "reply": "offscreen reply",
+             "sender": {
+               "id": $1,
+               "url": $2
+             }
+           })",
+        extension->id(), extension->GetResourceURL("background.js"));
+    base::Value result = BackgroundScriptExecutor::ExecuteScript(
+        profile(), extension->id(), "sendMessageFromBackground();",
+        BackgroundScriptExecutor::ResultCapture::kSendScriptResult);
+    EXPECT_THAT(result, base::test::IsJson(expected));
+  }
+
+  {
+    // Next, send a message in the other direction, from the offscreen document
+    // to the service worker.
+    std::string expected = content::JsReplace(
+        R"({
+             "msg": "message from offscreen",
+             "reply": "background reply",
+             "sender": {
+               "id": $1,
+               "origin": $2,
+               "url": $3
+             }
+           })",
+        extension->id(), extension->origin(), offscreen_url);
+    content::WebContents* contents = offscreen_document->host_contents();
+    ScriptResultQueue result_queue;
+    content::ExecuteScriptAsync(contents, "sendMessageFromOffscreen();");
+    base::Value result = result_queue.GetNextResult();
+    EXPECT_THAT(result, base::test::IsJson(expected));
+  }
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/user_host_restrictions_browsertest.cc b/chrome/browser/extensions/user_host_restrictions_browsertest.cc
index 6caf967d..b5eb613 100644
--- a/chrome/browser/extensions/user_host_restrictions_browsertest.cc
+++ b/chrome/browser/extensions/user_host_restrictions_browsertest.cc
@@ -2,16 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/extensions/extension_apitest.h"
+#include "chrome/browser/extensions/scripting_permissions_modifier.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/sessions/content/session_tab_helper.h"
 #include "content/public/test/browser_test.h"
 #include "extensions/browser/background_script_executor.h"
+#include "extensions/browser/notification_types.h"
 #include "extensions/browser/permissions_manager.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/extension_features.h"
+#include "extensions/common/permissions/permissions_data.h"
 #include "extensions/test/permissions_manager_waiter.h"
 #include "extensions/test/result_catcher.h"
 #include "extensions/test/test_extension_dir.h"
@@ -252,4 +257,139 @@
   }
 }
 
+// Tests that extensions with withheld host permissions are automatically
+// allowed to run on sites the user allows all extensions to run on.
+IN_PROC_BROWSER_TEST_P(UserHostRestrictionsBrowserTest, UserPermittedSites) {
+  ASSERT_TRUE(StartEmbeddedTestServer());
+
+  static constexpr char kManifest[] =
+      R"({
+           "name": "Test Extension",
+           "version": "0.1",
+           "manifest_version": 3,
+           "content_scripts": [{
+             "matches": ["http://allowed.example/*",
+                         "http://restricted.example/*"],
+             "js": ["content_script.js"],
+             "run_at": "document_end"
+           }]
+         })";
+
+  // Change the page title if the script is injected. Since the script is
+  // injected at document_end (which happens before the page completes loading),
+  // there shouldn't be a race condition in our checks.
+  static constexpr char kContentScript[] = "document.title = 'Injected';";
+
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), kContentScript);
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension);
+
+  const GURL allowed_url =
+      embedded_test_server()->GetURL("allowed.example", "/title1.html");
+  const GURL restricted_url =
+      embedded_test_server()->GetURL("restricted.example", "/title2.html");
+  const GURL unrequested_url =
+      embedded_test_server()->GetURL("unrequested.example", "/title3.html");
+
+  {
+    // Withhold extension host permissions. Wait for the notification to be
+    // fired to ensure all renderers and services have been properly updated.
+    auto is_update_for_extension =
+        [extension](const content::NotificationSource& source,
+                    const content::NotificationDetails& details) {
+          UpdatedExtensionPermissionsInfo* info =
+              content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
+          return info->extension->id() == extension->id();
+        };
+    content::WindowedNotificationObserver permissions_observer(
+        NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
+        base::BindLambdaForTesting(is_update_for_extension));
+    ScriptingPermissionsModifier(profile(), extension)
+        .SetWithholdHostPermissions(true);
+    permissions_observer.Wait();
+  }
+
+  const int kTabId = extension_misc::kUnknownTabId;
+
+  // Check the initial state of (withheld) permissions - the extension should
+  // have all requested host permissions withheld, and be denied on sites it
+  // didn't request.
+  EXPECT_EQ(PermissionsData::PageAccess::kWithheld,
+            extension->permissions_data()->GetContentScriptAccess(
+                allowed_url, kTabId, nullptr));
+  EXPECT_EQ(PermissionsData::PageAccess::kWithheld,
+            extension->permissions_data()->GetContentScriptAccess(
+                restricted_url, kTabId, nullptr));
+  EXPECT_EQ(PermissionsData::PageAccess::kDenied,
+            extension->permissions_data()->GetContentScriptAccess(
+                unrequested_url, kTabId, nullptr));
+
+  // Next, simulate the user granting all extensions access to `allowed_url` and
+  // `unrequested_url`.
+  PermissionsManager* permissions_manager = PermissionsManager::Get(profile());
+  auto add_user_permitted_site = [permissions_manager](const GURL& url) {
+    PermissionsManagerWaiter waiter(permissions_manager);
+    permissions_manager->AddUserPermittedSite(url::Origin::Create(url));
+    waiter.WaitForPermissionsChange();
+  };
+  add_user_permitted_site(allowed_url);
+  add_user_permitted_site(unrequested_url);
+
+  // Now, the extension should be allowed to run on the `allowed_url`, but
+  // `restricted_url` should remain withheld.
+  EXPECT_EQ(PermissionsData::PageAccess::kAllowed,
+            extension->permissions_data()->GetContentScriptAccess(
+                allowed_url, kTabId, nullptr));
+  EXPECT_EQ(PermissionsData::PageAccess::kWithheld,
+            extension->permissions_data()->GetContentScriptAccess(
+                restricted_url, kTabId, nullptr));
+  // Even though `unrequested_url` is a user-permitted site, the extension is
+  // denied access because it didn't request permission.
+  EXPECT_EQ(PermissionsData::PageAccess::kDenied,
+            extension->permissions_data()->GetContentScriptAccess(
+                unrequested_url, kTabId, nullptr));
+
+  // Verify permissions access in the renderer. `allowed_url`'s title should be
+  // changed, while `restricted_url` and `unrequested_url` should remain at
+  // their original (awesome) titles.
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), allowed_url));
+  static constexpr char16_t kInjectedTitle[] = u"Injected";
+  EXPECT_EQ(kInjectedTitle, GetActiveTab()->GetTitle());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), restricted_url));
+  EXPECT_EQ(u"Title Of Awesomeness", GetActiveTab()->GetTitle());
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), unrequested_url));
+  EXPECT_EQ(u"Title Of More Awesomeness", GetActiveTab()->GetTitle());
+
+  // Finally, remove the user-permitted `allowed_url`. Since the extension
+  // only had access to this URL via it being a user-permitted URL (and not
+  // via an explicit grant), the extension should lose access to the URL.
+  {
+    PermissionsManagerWaiter waiter(permissions_manager);
+    permissions_manager->RemoveUserPermittedSite(
+        url::Origin::Create(allowed_url));
+    waiter.WaitForPermissionsChange();
+  }
+
+  EXPECT_EQ(PermissionsData::PageAccess::kWithheld,
+            extension->permissions_data()->GetContentScriptAccess(
+                allowed_url, kTabId, nullptr));
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), allowed_url));
+  // Note that title1.html has no title, so it defaults to the URL - but it's
+  // sanitized for display (e.g. stripping HTTPS) so to avoid tying this too
+  // closely with the UI, we just check that it's not equal to the injected
+  // title.
+  EXPECT_NE(kInjectedTitle, GetActiveTab()->GetTitle());
+
+  // TODO(https://crbug.com/1268198): We could add more checks here to
+  // exercise the network service path, as we do for user restricted sites
+  // above. Since the user-permitted sites just grants the permissions to the
+  // extension, we don't *really* need to, but additional coverage never hurt
+  // (in case the implementation changes).
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0370cc0..4a64667 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -971,7 +971,7 @@
   {
     "name": "contextual-search-force-caption",
     "owners": [ "//chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/OWNERS", "contextual-search-eng@google.com" ],
-    "expiry_milestone": 104
+    "expiry_milestone": 110
   },
   {
     "name": "contextual-search-translations",
@@ -5303,28 +5303,28 @@
   },
   {
     "name": "related-searches",
-    "owners": [ "donnd", "related-searches-vteam@google.com" ],
-    "expiry_milestone": 104
+    "owners": [ "gangwu", "related-searches-vteam@google.com" ],
+    "expiry_milestone": 110
   },
   {
     "name": "related-searches-alternate-ux",
-    "owners": [ "donnd", "related-searches-vteam@google.com" ],
-    "expiry_milestone": 104
+    "owners": [ "gangwu", "related-searches-vteam@google.com" ],
+    "expiry_milestone": 110
   },
   {
     "name": "related-searches-in-bar",
-    "owners": [ "donnd", "related-searches-vteam@google.com" ],
-    "expiry_milestone": 104
+    "owners": [ "gangwu", "related-searches-vteam@google.com" ],
+    "expiry_milestone": 110
   },
   {
     "name": "related-searches-simplified-ux",
-    "owners": [ "donnd", "related-searches-vteam@google.com" ],
-    "expiry_milestone": 104
+    "owners": [ "gangwu", "related-searches-vteam@google.com" ],
+    "expiry_milestone": 110
   },
   {
     "name": "related-searches-ui",
-    "owners": [ "donnd", "related-searches-vteam@google.com" ],
-    "expiry_milestone": 104
+    "owners": [ "gangwu", "related-searches-vteam@google.com" ],
+    "expiry_milestone": 110
   },
   {
     "name": "release-notes-notification-all-channels",
diff --git a/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc b/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc
index dc47a83..061f32d 100644
--- a/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc
+++ b/chrome/browser/optimization_guide/page_content_annotations_service_factory.cc
@@ -121,6 +121,7 @@
         g_browser_process->GetApplicationLocale(),
         optimization_guide_keyed_service, history_service, proto_db_provider,
         profile_path,
+        optimization_guide_keyed_service->GetOptimizationGuideLogger(),
         base::ThreadPool::CreateSequencedTaskRunner(
             {base::MayBlock(), base::TaskPriority::BEST_EFFORT}));
   }
diff --git a/chrome/browser/partnerbookmarks/BUILD.gn b/chrome/browser/partnerbookmarks/BUILD.gn
index 36240ca..613dc43 100644
--- a/chrome/browser/partnerbookmarks/BUILD.gn
+++ b/chrome/browser/partnerbookmarks/BUILD.gn
@@ -6,28 +6,12 @@
 
 android_library("delegate_java") {
   sources = [
-    "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmark.java",
     "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarkIterator.java",
     "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegate.java",
     "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegateImpl.java",
-    "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottle.java",
-    "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksProviderIterator.java",
-    "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java",
   ]
 
-  deps = [
-    "//base:base_java",
-    "//base:jni_java",
-    "//build/android:build_java",
-    "//chrome/browser/partnercustomizations:java",
-    "//components/embedder_support/android:util_java",
-    "//third_party/androidx:androidx_annotation_annotation_java",
-    "//ui/android:ui_no_recycler_view_java",
-  ]
-
-  annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
-
-  srcjar_deps = [ "//chrome:partner_bookmarks_javagen" ]
+  deps = [ "//third_party/androidx:androidx_annotation_annotation_java" ]
 
   resources_package = "org.chromium.chrome.browser.partnerbookmarks"
 
@@ -44,25 +28,3 @@
     "//third_party/androidx:androidx_annotation_annotation_java",
   ]
 }
-
-generate_jni("jni_headers") {
-  sources = [ "java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReader.java" ]
-}
-
-robolectric_library("junit") {
-  sources = [
-    "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksFaviconThrottleTest.java",
-    "junit/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksReaderTest.java",
-  ]
-
-  deps = [
-    ":delegate_java",
-    "//base:base_java_test_support",
-    "//base:base_junit_test_support",
-    "//chrome/browser/partnercustomizations:java",
-    "//third_party/android_support_test_runner:runner_java",
-    "//third_party/androidx:androidx_test_runner_java",
-    "//third_party/junit:junit",
-    "//third_party/mockito:mockito_java",
-  ]
-}
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarkIterator.java b/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarkIterator.java
index 0b0fcb6..f4d1c23 100644
--- a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarkIterator.java
+++ b/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarkIterator.java
@@ -5,4 +5,4 @@
 package org.chromium.chrome.browser.partnerbookmarks;
 
 /** For now a placeholder. Intended to replace {@link PartnerBookmark.BookmarkIterator}. */
-public interface PartnerBookmarkIterator extends PartnerBookmark.BookmarkIterator {}
+public interface PartnerBookmarkIterator {}
diff --git a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegateImpl.java b/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegateImpl.java
index e090032..f5d90b5 100644
--- a/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegateImpl.java
+++ b/chrome/browser/partnerbookmarks/java/src/org/chromium/chrome/browser/partnerbookmarks/PartnerBookmarksDelegateImpl.java
@@ -11,6 +11,6 @@
     @Override
     @Nullable
     public PartnerBookmarkIterator createIterator() {
-        return PartnerBookmarksProviderIterator.createIfAvailable();
+        return null;
     }
 }
\ No newline at end of file
diff --git a/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc b/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc
index 8cc0bb8..2bb3866 100644
--- a/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc
+++ b/chrome/browser/segmentation_platform/default_model/feed_user_segment.cc
@@ -65,18 +65,10 @@
 constexpr std::array<int32_t, 1> kFeedEngagementInteracted{2};
 constexpr std::array<int32_t, 1> kFeedEngagementScrolled{4};
 
-constexpr std::array<MetadataWriter::UMAFeature, 13> kFeedUserUMAFeatures = {
-    MetadataWriter::UMAFeature::FromUserAction(
-        "ContentSuggestions.Feed.CardAction.Open",
-        14),
-    MetadataWriter::UMAFeature::FromUserAction(
-        "ContentSuggestions.Feed.CardAction.OpenInNewIncognitoTab",
-        14),
-    MetadataWriter::UMAFeature::FromUserAction(
-        "ContentSuggestions.Feed.CardAction.OpenInNewTab",
-        14),
+constexpr std::array<MetadataWriter::UMAFeature, 11> kFeedUserUMAFeatures = {
     MetadataWriter::UMAFeature::FromUserAction("MobileNTPMostVisited", 14),
     MetadataWriter::UMAFeature::FromUserAction("MobileNewTabOpened", 14),
+    MetadataWriter::UMAFeature::FromUserAction("MobileNewTabShown", 14),
     MetadataWriter::UMAFeature::FromUserAction("Home", 14),
     MetadataWriter::UMAFeature::FromUserAction("MobileMenuRecentTabs", 14),
     MetadataWriter::UMAFeature::FromUserAction("MobileMenuHistory", 14),
@@ -84,22 +76,22 @@
                                                14),
     MetadataWriter::UMAFeature::FromEnumHistogram(
         "ContentSuggestions.Feed.EngagementType",
-        14,
+        28,
         kFeedEngagementEngaged.data(),
         kFeedEngagementEngaged.size()),
     MetadataWriter::UMAFeature::FromEnumHistogram(
         "ContentSuggestions.Feed.EngagementType",
-        14,
+        28,
         kFeedEngagementSimple.data(),
         kFeedEngagementSimple.size()),
     MetadataWriter::UMAFeature::FromEnumHistogram(
         "ContentSuggestions.Feed.EngagementType",
-        14,
+        28,
         kFeedEngagementInteracted.data(),
         kFeedEngagementInteracted.size()),
     MetadataWriter::UMAFeature::FromEnumHistogram(
         "ContentSuggestions.Feed.EngagementType",
-        14,
+        28,
         kFeedEngagementScrolled.data(),
         kFeedEngagementScrolled.size()),
 };
@@ -208,15 +200,15 @@
 
   FeedUserSubsegment segment = FeedUserSubsegment::kNoNTPOrHomeOpened;
 
-  const bool feed_engaged = inputs[9] >= 2;
-  const bool feed_engaged_simple = inputs[10] >= 2;
-  const bool feed_interacted = inputs[11] >= 2;
-  const bool feed_scrolled = inputs[12] >= 2;
+  const bool feed_engaged = inputs[7] >= 2;
+  const bool feed_engaged_simple = inputs[8] >= 2;
+  const bool feed_interacted = inputs[9] >= 2;
+  const bool feed_scrolled = inputs[10] >= 2;
 
-  const bool mv_tiles_used = inputs[3] >= 2;
-  const bool return_to_tab_used = inputs[8] >= 2;
+  const bool mv_tiles_used = inputs[0] >= 2;
+  const bool return_to_tab_used = inputs[6] >= 2;
   const bool ntp_used = mv_tiles_used || return_to_tab_used;
-  const bool home_or_ntp_opened = (inputs[4] + inputs[5]) >= 4;
+  const bool home_or_ntp_opened = (inputs[1] + inputs[2] + inputs[3]) >= 2;
 
   if (feed_engaged) {
     segment = ntp_used ? FeedUserSubsegment::kNtpAndFeedEngaged
diff --git a/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc b/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc
index 439de001..e2bb8a1 100644
--- a/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc
+++ b/chrome/browser/segmentation_platform/default_model/feed_user_segment_unittest.cc
@@ -78,7 +78,7 @@
   ExpectInitAndFetchModel();
   ASSERT_TRUE(fetched_metadata_);
 
-  std::vector<float> input(13, 0);
+  std::vector<float> input(11, 0);
 
   absl::optional<float> result = ExpectExecutionWithInput(input);
   ASSERT_TRUE(result);
@@ -87,8 +87,8 @@
       FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore(
           "feed_user_segment_subsegment", *result, *fetched_metadata_)));
 
-  input[4] = 3;
-  input[5] = 2;
+  input[1] = 3;
+  input[2] = 2;
   result = ExpectExecutionWithInput(input);
   ASSERT_TRUE(result);
   EXPECT_EQ(
@@ -96,7 +96,7 @@
       FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore(
           "feed_user_segment_subsegment", *result, *fetched_metadata_)));
 
-  input[3] = 3;
+  input[0] = 3;
   result = ExpectExecutionWithInput(input);
   ASSERT_TRUE(result);
   EXPECT_EQ(
@@ -104,7 +104,7 @@
       FeedUserSegment::GetSubsegmentName(metadata_utils::ConvertToDiscreteScore(
           "feed_user_segment_subsegment", *result, *fetched_metadata_)));
 
-  input[10] = 3;
+  input[8] = 3;
   result = ExpectExecutionWithInput(input);
   ASSERT_TRUE(result);
   EXPECT_EQ(
diff --git a/chrome/browser/storage_access_api/api_browsertest.cc b/chrome/browser/storage_access_api/api_browsertest.cc
index 911b885d..a90ac08 100644
--- a/chrome/browser/storage_access_api/api_browsertest.cc
+++ b/chrome/browser/storage_access_api/api_browsertest.cc
@@ -34,7 +34,9 @@
 #include "net/dns/mock_host_resolver.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
+#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-forward.h"
 #include "ui/base/window_open_disposition.h"
 
 using content::BrowserThread;
@@ -137,86 +139,10 @@
     return ChildFrameAt(GetFrame(), 0);
   }
 
-  void TestThirdPartyIFrameStorageRequestsAccess(TestType test_type) {
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/browsing_data/site_data.html");
-
-    ExpectStorage(test_type, GetFrame(), false);
-    SetStorage(test_type, GetFrame());
-    ExpectStorage(test_type, GetFrame(), true);
-
-    SetBlockThirdPartyCookies(true);
-
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/browsing_data/site_data.html");
-    ExpectStorage(test_type, GetFrame(), false);
-    storage::test::CheckStorageAccessForFrame(GetFrame(), false);
-
-    // Allow all requests to b.com on a.com to access storage.
-    storage::test::RequestStorageAccessForFrame(GetFrame(), true);
-    storage::test::CheckStorageAccessForFrame(GetFrame(), true);
-
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/browsing_data/site_data.html");
-    ExpectStorage(test_type, GetFrame(), true);
-    storage::test::CheckStorageAccessForFrame(GetFrame(), true);
-  }
-
-  void TestNestedThirdPartyIFrameStorage(TestType test_type) {
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/iframe.html");
-    NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
-
-    ExpectStorage(test_type, GetNestedFrame(), false);
-    SetStorage(test_type, GetNestedFrame());
-    ExpectStorage(test_type, GetNestedFrame(), true);
-
-    SetBlockThirdPartyCookies(true);
-
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/iframe.html");
-    NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
-    ExpectStorage(test_type, GetNestedFrame(), false);
-    storage::test::CheckStorageAccessForFrame(GetNestedFrame(), false);
-
-    // Allow all requests to b.com on a.com to access storage.
-    storage::test::RequestStorageAccessForFrame(GetNestedFrame(), true);
-    storage::test::CheckStorageAccessForFrame(GetNestedFrame(), true);
-
-    NavigateToPageWithFrame("a.com");
-    NavigateFrameTo("b.com", "/iframe.html");
-    NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
-    ExpectStorage(test_type, GetNestedFrame(), true);
-    storage::test::CheckStorageAccessForFrame(GetNestedFrame(), true);
-  }
-
-  net::test_server::EmbeddedTestServer https_server_;
+  net::test_server::EmbeddedTestServer& https_server() { return https_server_; }
 
  private:
-  void ExpectStorage(TestType test_type,
-                     content::RenderFrameHost* frame,
-                     bool expected) {
-    switch (test_type) {
-      case TestType::kFrame:
-        storage::test::ExpectStorageForFrame(frame, expected);
-        return;
-      case TestType::kWorker:
-        storage::test::ExpectStorageForWorker(frame, expected);
-        return;
-    }
-  }
-
-  void SetStorage(TestType test_type, content::RenderFrameHost* frame) {
-    switch (test_type) {
-      case TestType::kFrame:
-        storage::test::SetStorageForFrame(frame);
-        return;
-      case TestType::kWorker:
-        storage::test::SetStorageForWorker(frame);
-        return;
-    }
-  }
-
+  net::test_server::EmbeddedTestServer https_server_;
   base::test::ScopedFeatureList feature_enable_;
 };
 
@@ -229,14 +155,14 @@
   base::HistogramTester histogram_tester;
 
   // Set a cookie on `b.com`.
-  content::SetCookie(browser()->profile(), https_server_.GetURL("b.com", "/"),
+  content::SetCookie(browser()->profile(), https_server().GetURL("b.com", "/"),
                      "thirdparty=1;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(browser()->profile(), GetURL("b.com"),
                                      "thirdparty=1");
 
   // Set a cookie on othersite.com.
   content::SetCookie(browser()->profile(),
-                     https_server_.GetURL("othersite.com", "/"),
+                     https_server().GetURL("othersite.com", "/"),
                      "thirdparty=other;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(
       browser()->profile(), GetURL("othersite.com"), "thirdparty=other");
@@ -254,10 +180,11 @@
   // Our use counter should not have fired yet, so we should have 0 occurrences.
   histogram_tester.ExpectBucketCount(
       kUseCounterHistogram,
-      /*kStorageAccessAPI_HasStorageAccess_Method=*/3310, 0);
+      blink::mojom::WebFeature::kStorageAccessAPI_HasStorageAccess_Method, 0);
   histogram_tester.ExpectBucketCount(
       kUseCounterHistogram,
-      /*kStorageAccessAPI_requestStorageAccess_Method=*/3311, 0);
+      blink::mojom::WebFeature::kStorageAccessAPI_requestStorageAccess_Method,
+      0);
 
   // Navigate iframe to a cross-site, cookie-reading endpoint, and verify that
   // the cookie is sent:
@@ -268,10 +195,11 @@
   // Since the frame has navigated we should see the use counter telem appear.
   histogram_tester.ExpectBucketCount(
       kUseCounterHistogram,
-      /*kStorageAccessAPI_HasStorageAccess_Method=*/3310, 1);
+      blink::mojom::WebFeature::kStorageAccessAPI_HasStorageAccess_Method, 1);
   histogram_tester.ExpectBucketCount(
       kUseCounterHistogram,
-      /*kStorageAccessAPI_requestStorageAccess_Method=*/3311, 1);
+      blink::mojom::WebFeature::kStorageAccessAPI_requestStorageAccess_Method,
+      1);
 
   // Navigate iframe to othersite.com and verify that the cookie is not sent.
   NavigateFrameTo("othersite.com", "/echoheader?cookie");
@@ -338,7 +266,7 @@
   SetBlockThirdPartyCookies(true);
 
   // Set a cookie on `b.com`.
-  content::SetCookie(browser()->profile(), https_server_.GetURL("b.com", "/"),
+  content::SetCookie(browser()->profile(), https_server().GetURL("b.com", "/"),
                      "thirdparty=1;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(browser()->profile(), GetURL("b.com"),
                                      "thirdparty=1");
@@ -353,7 +281,7 @@
   // Block all cookies with a user setting for b.com.
   auto cookie_settings =
       CookieSettingsFactory::GetForProfile(browser()->profile());
-  GURL url = https_server_.GetURL("b.com", "/");
+  GURL url = https_server().GetURL("b.com", "/");
   cookie_settings->SetCookieSetting(url, ContentSetting::CONTENT_SETTING_BLOCK);
   storage::test::CheckStorageAccessForFrame(GetFrame(), false);
 
@@ -380,29 +308,6 @@
   storage::test::CheckStorageAccessForFrame(GetNestedFrame(), false);
 }
 
-// Validate that the Storage Access API will unblock other types of storage
-// access when a grant is given and that it only applies to the top-level/third
-// party pair requested on.
-IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest,
-                       ThirdPartyIFrameStorageRequestsAccessForFrame) {
-  TestThirdPartyIFrameStorageRequestsAccess(TestType::kFrame);
-}
-
-IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest,
-                       ThirdPartyIFrameStorageRequestsAccessForWorker) {
-  TestThirdPartyIFrameStorageRequestsAccess(TestType::kWorker);
-}
-
-IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest,
-                       NestedThirdPartyIFrameStorageForFrame) {
-  TestNestedThirdPartyIFrameStorage(TestType::kFrame);
-}
-
-IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest,
-                       NestedThirdPartyIFrameStorageForWorker) {
-  TestNestedThirdPartyIFrameStorage(TestType::kWorker);
-}
-
 // Test third-party cookie blocking of features that allow to communicate
 // between tabs such as SharedWorkers.
 IN_PROC_BROWSER_TEST_F(StorageAccessAPIBrowserTest, MultiTabTest) {
@@ -444,7 +349,7 @@
   SetBlockThirdPartyCookies(true);
 
   // Set a cookie on `b.com`.
-  content::SetCookie(browser()->profile(), https_server_.GetURL("b.com", "/"),
+  content::SetCookie(browser()->profile(), https_server().GetURL("b.com", "/"),
                      "thirdparty=1;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(browser()->profile(), GetURL("b.com"),
                                      "thirdparty=1");
@@ -522,11 +427,11 @@
   SetBlockThirdPartyCookies(true);
 
   // Set a cookie on `b.com` and `c.com`.
-  content::SetCookie(browser()->profile(), https_server_.GetURL("b.com", "/"),
+  content::SetCookie(browser()->profile(), https_server().GetURL("b.com", "/"),
                      "thirdparty=1;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(browser()->profile(), GetURL("b.com"),
                                      "thirdparty=1");
-  content::SetCookie(browser()->profile(), https_server_.GetURL("c.com", "/"),
+  content::SetCookie(browser()->profile(), https_server().GetURL("c.com", "/"),
                      "thirdparty=1;SameSite=None;Secure");
   storage::test::ExpectCookiesOnHost(browser()->profile(), GetURL("c.com"),
                                      "thirdparty=1");
@@ -581,4 +486,101 @@
   ExpectNestedFrameContent("thirdparty=1");
 }
 
+class StorageAccessAPIStorageBrowserTest
+    : public StorageAccessAPIBrowserTest,
+      public testing::WithParamInterface<TestType> {
+ public:
+  TestType GetTestType() const { return GetParam(); }
+
+  void ExpectStorage(TestType test_type,
+                     content::RenderFrameHost* frame,
+                     bool expected) {
+    switch (test_type) {
+      case TestType::kFrame:
+        storage::test::ExpectStorageForFrame(frame, expected);
+        return;
+      case TestType::kWorker:
+        storage::test::ExpectStorageForWorker(frame, expected);
+        return;
+    }
+  }
+
+  void SetStorage(TestType test_type, content::RenderFrameHost* frame) {
+    switch (test_type) {
+      case TestType::kFrame:
+        storage::test::SetStorageForFrame(frame);
+        return;
+      case TestType::kWorker:
+        storage::test::SetStorageForWorker(frame);
+        return;
+    }
+  }
+};
+
+// Validate that the Storage Access API will unblock other types of storage
+// access when a grant is given and that it only applies to the top-level/third
+// party pair requested on.
+IN_PROC_BROWSER_TEST_P(StorageAccessAPIStorageBrowserTest,
+                       ThirdPartyIFrameStorageRequestsAccess) {
+  const TestType test_type = GetTestType();
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/browsing_data/site_data.html");
+
+  ExpectStorage(test_type, GetFrame(), false);
+  SetStorage(test_type, GetFrame());
+  ExpectStorage(test_type, GetFrame(), true);
+
+  SetBlockThirdPartyCookies(true);
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/browsing_data/site_data.html");
+  ExpectStorage(test_type, GetFrame(), false);
+  storage::test::CheckStorageAccessForFrame(GetFrame(), false);
+
+  // Allow all requests to b.com on a.com to access storage.
+  storage::test::RequestStorageAccessForFrame(GetFrame(), true);
+  storage::test::CheckStorageAccessForFrame(GetFrame(), true);
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/browsing_data/site_data.html");
+  ExpectStorage(test_type, GetFrame(), true);
+  storage::test::CheckStorageAccessForFrame(GetFrame(), true);
+}
+
+IN_PROC_BROWSER_TEST_P(StorageAccessAPIStorageBrowserTest,
+                       NestedThirdPartyIFrameStorage) {
+  const TestType test_type = GetTestType();
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/iframe.html");
+  NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
+
+  ExpectStorage(test_type, GetNestedFrame(), false);
+  SetStorage(test_type, GetNestedFrame());
+  ExpectStorage(test_type, GetNestedFrame(), true);
+
+  SetBlockThirdPartyCookies(true);
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/iframe.html");
+  NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
+  ExpectStorage(test_type, GetNestedFrame(), false);
+  storage::test::CheckStorageAccessForFrame(GetNestedFrame(), false);
+
+  // Allow all requests to b.com on a.com to access storage.
+  storage::test::RequestStorageAccessForFrame(GetNestedFrame(), true);
+  storage::test::CheckStorageAccessForFrame(GetNestedFrame(), true);
+
+  NavigateToPageWithFrame("a.com");
+  NavigateFrameTo("b.com", "/iframe.html");
+  NavigateNestedFrameTo("c.com", "/browsing_data/site_data.html");
+  ExpectStorage(test_type, GetNestedFrame(), true);
+  storage::test::CheckStorageAccessForFrame(GetNestedFrame(), true);
+}
+
+INSTANTIATE_TEST_SUITE_P(/*no prefix*/,
+                         StorageAccessAPIStorageBrowserTest,
+                         testing::Values(TestType::kFrame, TestType::kWorker));
+
 }  // namespace
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc
index c76d5a5..1bb7fbb8 100644
--- a/chrome/browser/themes/theme_service.cc
+++ b/chrome/browser/themes/theme_service.cc
@@ -73,6 +73,7 @@
 #endif
 
 #if BUILDFLAG(IS_LINUX)
+#include "ui/ozone/public/ozone_platform.h"
 #include "ui/views/linux_ui/linux_ui.h"
 #endif
 
@@ -481,6 +482,12 @@
 
 bool ThemeService::ShouldUseCustomFrame() const {
 #if BUILDFLAG(IS_LINUX)
+  if (!ui::OzonePlatform::GetInstance()
+           ->GetPlatformRuntimeProperties()
+           .supports_server_side_window_decorations) {
+    return true;
+  }
+
   return profile_->GetPrefs()->GetBoolean(prefs::kUseCustomChromeFrame);
 #else
   return true;
diff --git a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc b/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc
index 4914236..343528c1 100644
--- a/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc
+++ b/chrome/browser/ui/ash/desks/chrome_desks_templates_delegate.cc
@@ -46,6 +46,7 @@
 #include "components/favicon_base/favicon_util.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 #include "components/services/app_service/public/cpp/app_types.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/types_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/user_manager/user_manager.h"
@@ -254,7 +255,8 @@
     app_launch_info->file_paths = app_restore_data->file_paths;
     if (app_restore_data->intent.has_value() &&
         app_restore_data->intent.value()) {
-      app_launch_info->intent = app_restore_data->intent.value()->Clone();
+      app_launch_info->intent =
+          apps::ConvertMojomIntentToIntent(app_restore_data->intent.value());
     }
   }
 
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
index 4347871..8a7c96e 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.cc
@@ -66,13 +66,6 @@
 #include "components/sync/driver/sync_user_settings.h"
 #include "components/user_manager/known_user.h"
 #include "components/user_manager/user_manager.h"
-#include "components/value_store/value_store.h"
-#include "extensions/browser/api/storage/backend_task_runner.h"
-#include "extensions/browser/api/storage/storage_frontend.h"
-#include "extensions/browser/event_router.h"
-#include "extensions/browser/extension_registry.h"
-#include "extensions/common/constants.h"
-#include "extensions/common/extension.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "google_apis/gaia/google_service_auth_error.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -80,7 +73,6 @@
 #include "url/gurl.h"
 
 using ::ash::ProfileHelper;
-using extension_misc::kWallpaperManagerId;
 using file_manager::VolumeManager;
 using session_manager::SessionManager;
 using wallpaper_handlers::BackdropSurpriseMeImageFetcher;
@@ -89,8 +81,6 @@
 
 // Known user keys.
 const char kWallpaperFilesId[] = "wallpaper-files-id";
-constexpr char kChromeAppDailyRefreshInfoPref[] = "daily-refresh-info-key";
-constexpr char kChromeAppCollectionId[] = "collectionId";
 constexpr char kDriveFsWallpaperDirName[] = "Chromebook Wallpaper";
 // Encoded in |WallpaperControllerImpl.ResizeAndEncodeImage|.
 constexpr char kDriveFsWallpaperFileName[] = "wallpaper.jpg";
@@ -179,41 +169,6 @@
   return nullptr;
 }
 
-// Extract daily refresh collection id from |value_store|. If unable to fetch
-// the daily refresh collection id, or the user does not have daily refresh
-// configured, returns empty string. This must be run on the same sequence
-// that |value_store| came from.
-std::string GetDailyRefreshCollectionId(value_store::ValueStore* value_store) {
-  if (!value_store)
-    return std::string();
-
-  auto read_result = value_store->Get(kChromeAppDailyRefreshInfoPref);
-
-  if (!read_result.status().ok())
-    return std::string();
-
-  const auto* daily_refresh_info_string =
-      read_result.settings().GetDict().FindString(
-          kChromeAppDailyRefreshInfoPref);
-
-  if (!daily_refresh_info_string)
-    return std::string();
-
-  const absl::optional<base::Value> daily_refresh_info =
-      base::JSONReader::Read(*daily_refresh_info_string);
-
-  if (!daily_refresh_info)
-    return std::string();
-
-  const auto* collection_id =
-      daily_refresh_info->GetDict().FindString(kChromeAppCollectionId);
-
-  if (!collection_id)
-    return std::string();
-
-  return *collection_id;
-}
-
 base::FilePath GetDriveFsWallpaperDir(Profile* profile) {
   CHECK(profile);
 
@@ -615,13 +570,6 @@
   ObserveVolumeManagerForAccountId(account_id);
 }
 
-void WallpaperControllerClientImpl::MigrateCollectionIdFromValueStoreForTesting(
-    const AccountId& account_id,
-    value_store::ValueStore* value_store) {
-  SetDailyRefreshCollectionId(account_id,
-                              GetDailyRefreshCollectionId(value_store));
-}
-
 void WallpaperControllerClientImpl::DeviceWallpaperImageFilePathChanged() {
   wallpaper_controller_->SetDevicePolicyWallpaperPath(
       GetDeviceWallpaperImageFilePath());
@@ -689,30 +637,7 @@
 void WallpaperControllerClientImpl::MigrateCollectionIdFromChromeApp(
     const AccountId& account_id,
     base::OnceCallback<void(const std::string&)> result_callback) {
-  Profile* profile = ProfileHelper::Get()->GetProfileByAccountId(account_id);
-  auto* extension_registry = extensions::ExtensionRegistry::Get(profile);
-  const extensions::Extension* extension =
-      extension_registry->GetInstalledExtension(kWallpaperManagerId);
-
-  // Although not now, there will be a day where this application no longer
-  // exists.
-  if (!extension) {
-    SetDailyRefreshCollectionId(account_id, std::string());
-    return;
-  }
-
-  // Get a ptr to current sequence.
-  const scoped_refptr<base::SequencedTaskRunner> task_runner =
-      base::SequencedTaskRunnerHandle::Get();
-
-  auto* storage_frontend = extensions::StorageFrontend::Get(profile);
-  // Callback runs on a backend sequence.
-  storage_frontend->RunWithStorage(
-      extension, extensions::settings_namespace::LOCAL,
-      base::BindOnce(
-          &WallpaperControllerClientImpl::OnGetWallpaperChromeAppValueStore,
-          storage_weak_factory_.GetWeakPtr(), task_runner,
-          std::move(result_callback)));
+  std::move(result_callback).Run(std::string());
 }
 
 void WallpaperControllerClientImpl::FetchDailyRefreshWallpaper(
@@ -809,18 +734,6 @@
       local_state_->GetString(prefs::kDeviceWallpaperImageFilePath));
 }
 
-void WallpaperControllerClientImpl::OnGetWallpaperChromeAppValueStore(
-    scoped_refptr<base::SequencedTaskRunner> main_task_runner,
-    base::OnceCallback<void(const std::string&)> result_callback,
-    value_store::ValueStore* value_store) {
-  DCHECK(extensions::IsOnBackendSequence());
-  std::string collection_id = GetDailyRefreshCollectionId(value_store);
-  // Jump back to original task runner.
-  main_task_runner->PostTask(
-      FROM_HERE,
-      base::BindOnce(std::move(result_callback), std::move(collection_id)));
-}
-
 void WallpaperControllerClientImpl::SetDailyRefreshCollectionId(
     const AccountId& account_id,
     const std::string& collection_id) {
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
index efd9a7c..181b544 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl.h
@@ -30,10 +30,6 @@
 class SequencedTaskRunner;
 }  // namespace base
 
-namespace value_store {
-class ValueStore;
-}
-
 namespace {
 class WallpaperControllerClientImplTest;
 }
@@ -159,9 +155,6 @@
   bool IsActiveUserWallpaperControlledByPolicy();
   ash::WallpaperInfo GetActiveUserWallpaperInfo();
   bool ShouldShowWallpaperSetting();
-  void MigrateCollectionIdFromValueStoreForTesting(
-      const AccountId& account_id,
-      value_store::ValueStore* storage);
   // Record Ash.Wallpaper.Source metric when a new wallpaper is set,
   // either by built-in Wallpaper app or a third party extension/app.
   void RecordWallpaperSourceUMA(const ash::WallpaperType type);
@@ -183,14 +176,6 @@
 
   base::FilePath GetDeviceWallpaperImageFilePath();
 
-  // Used as callback to |MigrateCollectionIdFromChromeApp|. Called on backend
-  // task runner. Extracts the daily refresh collection id and calls
-  // |SetDailyRefreshCollectionId| on main task runner.
-  void OnGetWallpaperChromeAppValueStore(
-      scoped_refptr<base::SequencedTaskRunner> main_task_runner,
-      base::OnceCallback<void(const std::string&)> result_callback,
-      value_store::ValueStore* value_store);
-
   // Passes |collection_id| to wallpaper controller on main task runner.
   void SetDailyRefreshCollectionId(const AccountId& account_id,
                                    const std::string& collection_id);
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/wallpaper_controller_client_impl_unittest.cc
index 96a6780..3be39b13 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client_impl_unittest.cc
@@ -19,8 +19,6 @@
 
 namespace {
 
-constexpr char kChromeAppDailyRefreshInfoKey[] = "daily-refresh-info-key";
-
 class WallpaperControllerClientImplTest : public testing::Test {
  public:
   WallpaperControllerClientImplTest()
@@ -71,89 +69,6 @@
   EXPECT_TRUE(controller()->was_client_set());
 }
 
-TEST_F(WallpaperControllerClientImplTest, MigrateCollectionIdFromValueStore) {
-  value_store::TestingValueStore value_store;
-
-  // There is also a resume token and an enabled state, but that's not what is
-  // being tested here, so only populate collectionId.
-  std::string json("{\"collectionId\" : \"fun_collection\"}");
-  value_store.Set(0, kChromeAppDailyRefreshInfoKey, base::Value(json));
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id,
-                                                        &value_store);
-
-  EXPECT_EQ("fun_collection", controller()->collection_id());
-}
-
-TEST_F(WallpaperControllerClientImplTest,
-       MigrateCollectionIdFromValueStoreNoCollectionId) {
-  value_store::TestingValueStore value_store;
-
-  // There is also a resume token and an enabled state, but that's not what is
-  // being tested here, so only populate collectionId.
-  std::string json("{\"collectionId\" : null}");
-  value_store.Set(0, kChromeAppDailyRefreshInfoKey, base::Value(json));
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id,
-                                                        &value_store);
-
-  EXPECT_EQ(std::string(), controller()->collection_id());
-}
-
-TEST_F(WallpaperControllerClientImplTest,
-       MigrateCollectionIdFromValueStoreNoStore) {
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id, nullptr);
-
-  EXPECT_EQ(std::string(), controller()->collection_id());
-}
-
-TEST_F(WallpaperControllerClientImplTest,
-       MigrateCollectionIdFromValueStoreNotOKStatusCode) {
-  using StatusCode = value_store::ValueStore::StatusCode;
-
-  value_store::TestingValueStore value_store;
-  value_store.set_status_code(StatusCode::OTHER_ERROR);
-
-  // There is also a resume token and an enabled state, but that's not what is
-  // being tested here, so only populate collectionId.
-  std::string json("{\"collectionId\" : \"fun_collection\"}");
-  value_store.Set(0, kChromeAppDailyRefreshInfoKey, base::Value(json));
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id,
-                                                        &value_store);
-
-  EXPECT_EQ(std::string(), controller()->collection_id());
-}
-
-TEST_F(WallpaperControllerClientImplTest,
-       MigrateCollectionIdFromValueStoreNoPref) {
-  value_store::TestingValueStore value_store;
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id,
-                                                        &value_store);
-
-  EXPECT_EQ(std::string(), controller()->collection_id());
-}
-
-TEST_F(WallpaperControllerClientImplTest,
-       MigrateCollectionIdFromValueStoreMalformedPref) {
-  value_store::TestingValueStore value_store;
-  std::string json("{");
-  value_store.Set(0, kChromeAppDailyRefreshInfoKey, base::Value(json));
-  AccountId account_id =
-      AccountId::FromUserEmailGaiaId("fake@test.com", "444444");
-  client()->MigrateCollectionIdFromValueStoreForTesting(account_id,
-                                                        &value_store);
-
-  EXPECT_EQ(std::string(), controller()->collection_id());
-}
-
 TEST_F(WallpaperControllerClientImplTest, IsWallpaperSyncEnabledNoProfile) {
   AccountId account_id =
       AccountId::FromUserEmailGaiaId("idontexist@test.com", "444444");
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
index 23e0e37..3b11e9a 100644
--- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -480,6 +480,9 @@
   EXPECT_THAT(histogram_tester()->GetAllSamples(
                   "Bookmarks.Count.OnProfileLoad.UniqueUrlAndTitleAndParent"),
               testing::ElementsAre(base::Bucket(/*min=*/6, /*count=*/1)));
+  EXPECT_THAT(histogram_tester()->GetAllSamples(
+                  "Bookmarks.Times.OnProfileLoad.TimeSinceAdded"),
+              testing::ElementsAre(base::Bucket(/*min=*/0, /*count=*/1)));
 }
 
 #endif  // !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 458af71..ce86697 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1982,6 +1982,7 @@
     case extensions::Feature::BLESSED_WEB_PAGE_CONTEXT:
     case extensions::Feature::CONTENT_SCRIPT_CONTEXT:
     case extensions::Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
+    case extensions::Feature::OFFSCREEN_EXTENSION_CONTEXT:
     case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT:
     case extensions::Feature::UNSPECIFIED_CONTEXT:
     case extensions::Feature::WEBUI_CONTEXT:
diff --git a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
index ca7d6bd..7788ab3 100644
--- a/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
+++ b/chrome/browser/ui/omnibox/chrome_omnibox_edit_controller.cc
@@ -40,10 +40,11 @@
       match_selection_timestamp, destination_url_entered_without_scheme, text,
       match, alternative_nav_match);
 
-  auto navigation = chrome::OpenCurrentURL(browser_);
-
-  ChromeOmniboxNavigationObserver::Create(navigation.get(), profile_, text,
-                                          match, alternative_nav_match);
+  if (browser_) {
+    auto navigation = chrome::OpenCurrentURL(browser_);
+    ChromeOmniboxNavigationObserver::Create(navigation.get(), profile_, text,
+                                            match, alternative_nav_match);
+  }
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
   extensions::MaybeShowExtensionControlledSearchNotification(
diff --git a/chrome/browser/ui/views/frame/browser_frame.cc b/chrome/browser/ui/views/frame/browser_frame.cc
index 0d4c12f..236be71 100644
--- a/chrome/browser/ui/views/frame/browser_frame.cc
+++ b/chrome/browser/ui/views/frame/browser_frame.cc
@@ -361,6 +361,9 @@
 
 ui::ColorProviderManager::Key BrowserFrame::GetColorProviderKey() const {
   auto key = Widget::GetColorProviderKey();
+  key.frame_type = UseCustomFrame()
+                       ? ui::ColorProviderManager::FrameType::kChromium
+                       : ui::ColorProviderManager::FrameType::kNative;
   auto* app_controller = browser_view_->browser()->app_controller();
   key.app_controller =
       app_controller ? app_controller->get_weak_ref() : nullptr;
diff --git a/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux_browsertest.cc b/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux_browsertest.cc
index 841de650..22b873e 100644
--- a/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux_browsertest.cc
+++ b/chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux_browsertest.cc
@@ -4,13 +4,17 @@
 
 #include "chrome/browser/ui/views/frame/desktop_browser_frame_aura_linux.h"
 
+#include "base/test/bind.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/test/browser_test.h"
+#include "ui/color/color_provider_manager.h"
 #include "ui/ozone/public/ozone_platform.h"
 
 using DesktopBrowserFrameAuraLinuxTest = InProcessBrowserTest;
@@ -30,12 +34,34 @@
   return bounds.size();
 }
 
+void VerifyColorsForFrameType(const Browser* browser, bool use_custom_frame) {
+  ThemeService* theme_service =
+      ThemeServiceFactory::GetForProfile(browser->profile());
+  EXPECT_EQ(use_custom_frame, theme_service->ShouldUseCustomFrame());
+
+  ui::ColorProviderManager::ResetForTesting();
+
+  bool initialized_color_provider_for_custom_frame;
+  ui::ColorProviderManager::GetForTesting().AppendColorProviderInitializer(
+      base::BindLambdaForTesting([&initialized_color_provider_for_custom_frame](
+                                     ui::ColorProvider* provider,
+                                     const ui::ColorProviderManager::Key& key) {
+        initialized_color_provider_for_custom_frame =
+            key.frame_type == ui::ColorProviderManager::FrameType::kChromium;
+      }));
+  ASSERT_NE(nullptr,
+            BrowserView::GetBrowserViewForBrowser(browser)->GetColorProvider());
+  EXPECT_EQ(use_custom_frame, initialized_color_provider_for_custom_frame);
+
+  ui::ColorProviderManager::ResetForTesting();
+}
+
 }  // namespace
 
 // Tests that DesktopBrowserFrameAuraLinux::UseCustomFrame() returns the correct
 // value that respects 1) the current value of the user preference and
 // 2) capabilities of the platform.
-// Also tests the regression found in crbug.com/1243937.
+// Also tests the regressions found in crbug.com/1243937 and crbug.com/1329756.
 IN_PROC_BROWSER_TEST_F(DesktopBrowserFrameAuraLinuxTest, UseCustomFrame) {
   const BrowserView* const browser_view =
       BrowserView::GetBrowserViewForBrowser(browser());
@@ -65,6 +91,7 @@
           pref_service->SetBoolean(prefs::kUseCustomChromeFrame, setting);
           EXPECT_EQ(frame->UseCustomFrame(), setting)
               << " when setting is " << setting;
+          VerifyColorsForFrameType(browser(), frame->UseCustomFrame());
         }
       } else {
         // This platform either does not support overriding the property or does
@@ -74,6 +101,7 @@
           pref_service->SetBoolean(prefs::kUseCustomChromeFrame, setting);
           EXPECT_TRUE(frame->UseCustomFrame())
               << " when setting is " << setting;
+          VerifyColorsForFrameType(browser(), frame->UseCustomFrame());
         }
       }
     }
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
index e664b47..23e9171a 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_chromeos.cc
@@ -158,7 +158,7 @@
   // Enable immersive mode if the widget is activated. Do not disable immersive
   // mode if the widget deactivates, but is not minimized.
   chromeos::ImmersiveFullscreenController::EnableForWidget(
-      widget, active && !widget->IsMinimized());
+      widget, active || !widget->IsMinimized());
 }
 
 void ImmersiveModeControllerChromeos::LayoutBrowserRootView() {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index e425067..a61f9d5 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -627,13 +627,13 @@
   // the cursor are visible. If possible given the prior guarantee, also
   // guarantees |kPadTrailing| chars of the text following the cursor are
   // visible.
-  static const uint32_t kPadTrailing = 30;
-  static const uint32_t kPadLeading = 10;
+  static const size_t kPadTrailing = 30;
+  static const size_t kPadLeading = 10;
 
   // We use SetTextWithoutCaretBoundsChangeNotification() in order to avoid
   // triggering accessibility events multiple times.
   SetTextWithoutCaretBoundsChangeNotification(text, ranges[0].end());
-  Scroll({0, std::min<size_t>(ranges[0].end() + kPadTrailing, text.size()),
+  Scroll({0, std::min(ranges[0].end() + kPadTrailing, text.size()),
           ranges[0].end() - std::min(kPadLeading, ranges[0].end())});
   // Setting the primary selected range will also fire an appropriate final
   // accessibility event after the changes above.
@@ -1729,7 +1729,7 @@
   model()->AdjustTextForCopy(GetSelectedRange().GetMin(), &selected_text, &url,
                              &write_url);
   if (IsSelectAll()) {
-    UMA_HISTOGRAM_COUNTS_1M("Omnibox.CutOrCopyAllText", 1);
+    UMA_HISTOGRAM_COUNTS_1M(OmniboxEditModel::kCutOrCopyAllTextHistogram, 1);
 
     if (clipboard_buffer != ui::ClipboardBuffer::kSelection &&
         location_bar_view_) {
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_browsertest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_browsertest.cc
index 3b7c715..d7ed86c 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_browsertest.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_browsertest.cc
@@ -21,24 +21,14 @@
 const char kFirstTestFeatureId[] = "feature-1";
 const base::Feature kTestFeature1{"FeatureName1",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Experiment platform to use for feature flags.
-unsigned short GetPlatformToUse() {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  return flags_ui::FlagsState::GetCurrentPlatform() | flags_ui::kOsCrOS;
-#else
-  return flags_ui::FlagsState::GetCurrentPlatform();
-#endif
-}
-
 }  // namespace
 
 class ChromeLabsUiTest : public DialogBrowserTest {
  public:
   ChromeLabsUiTest()
-      : scoped_feature_entries_(
-            {{kFirstTestFeatureId, "", "", GetPlatformToUse(),
-              FEATURE_VALUE_TYPE(kTestFeature1)}}) {
+      : scoped_feature_entries_({{kFirstTestFeatureId, "", "",
+                                  flags_ui::FlagsState::GetCurrentPlatform(),
+                                  FEATURE_VALUE_TYPE(kTestFeature1)}}) {
     scoped_feature_list_.InitAndEnableFeature(features::kChromeLabs);
 
     std::vector<LabInfo> test_feature_info = {
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
index 95429fb8..7f2e748 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_button_unittest.cc
@@ -47,15 +47,6 @@
 const base::Feature kTestFeatureExpired{"Expired",
                                         base::FEATURE_DISABLED_BY_DEFAULT};
 
-// Experiment platform to use for feature flags.
-unsigned short GetPlatformToUse() {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  return flags_ui::FlagsState::GetCurrentPlatform() | flags_ui::kOsCrOS;
-#else
-  return flags_ui::FlagsState::GetCurrentPlatform();
-#endif
-}
-
 }  // namespace
 
 class ChromeLabsButtonTest : public TestWithBrowserView {
@@ -67,9 +58,9 @@
         user_manager_enabler_(base::WrapUnique(user_manager_)),
 #endif
 
-        scoped_feature_entries_(
-            {{kFirstTestFeatureId, "", "", GetPlatformToUse(),
-              FEATURE_VALUE_TYPE(kTestFeature1)}}) {
+        scoped_feature_entries_({{kFirstTestFeatureId, "", "",
+                                  flags_ui::FlagsState::GetCurrentPlatform(),
+                                  FEATURE_VALUE_TYPE(kTestFeature1)}}) {
   }
   void SetUp() override {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
@@ -233,9 +224,9 @@
     : public TestWithBrowserView {
  public:
   ChromeLabsButtonOnlyExpiredFeaturesAvailableTest()
-      : scoped_feature_entries_(
-            {{kExpiredFlagTestFeatureId, "", "", GetPlatformToUse(),
-              FEATURE_VALUE_TYPE(kTestFeatureExpired)}}) {
+      : scoped_feature_entries_({{kExpiredFlagTestFeatureId, "", "",
+                                  flags_ui::FlagsState::GetCurrentPlatform(),
+                                  FEATURE_VALUE_TYPE(kTestFeatureExpired)}}) {
     flags::testing::SetFlagExpiration(kExpiredFlagTestFeatureId, 0);
   }
   void SetUp() override {
diff --git a/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc b/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc
index 108146c..088f73ee 100644
--- a/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc
+++ b/chrome/browser/ui/views/toolbar/chrome_labs_unittest.cc
@@ -77,15 +77,6 @@
 const flags_ui::FeatureEntry::FeatureVariation kTestVariations2[] = {
     {"Description", kTestVariationOther2, 1, nullptr}};
 
-// Experiment platform to use for feature flags.
-unsigned short GetPlatformToUse() {
-#if BUILDFLAG(IS_CHROMEOS_LACROS)
-  return flags_ui::FlagsState::GetCurrentPlatform() | flags_ui::kOsCrOS;
-#else
-  return flags_ui::FlagsState::GetCurrentPlatform();
-#endif
-}
-
 std::vector<LabInfo> TestLabInfo() {
   std::vector<LabInfo> test_feature_info;
   test_feature_info.emplace_back(LabInfo(kFirstTestFeatureId, u"", u"", "",
@@ -118,9 +109,11 @@
         user_manager_enabler_(base::WrapUnique(user_manager_)),
 #endif
         scoped_feature_entries_(
-            {{kFirstTestFeatureId, "", "", GetPlatformToUse(),
+            {{kFirstTestFeatureId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_VALUE_TYPE(kTestFeature1)},
-             {kTestFeatureWithVariationId, "", "", GetPlatformToUse(),
+             {kTestFeatureWithVariationId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature2,
                                              kTestVariations2,
                                              "TestTrial")},
@@ -128,7 +121,8 @@
              // compatible with the current platform.
              {kThirdTestFeatureId, "", "", 0,
               FEATURE_VALUE_TYPE(kTestFeature3)},
-             {kExpiredFlagTestFeatureId, "", "", GetPlatformToUse(),
+             {kExpiredFlagTestFeatureId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_VALUE_TYPE(kExpiredFlagTestFeature)}}) {
     // Set expiration milestone such that the flag is expired.
     flags::testing::SetFlagExpiration(kExpiredFlagTestFeatureId, 0);
@@ -257,9 +251,11 @@
         user_manager_enabler_(base::WrapUnique(user_manager_)),
 #endif
         scoped_feature_entries_(
-            {{kFirstTestFeatureId, "", "", GetPlatformToUse(),
+            {{kFirstTestFeatureId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_VALUE_TYPE(kTestFeature1)},
-             {kTestFeatureWithVariationId, "", "", GetPlatformToUse(),
+             {kTestFeatureWithVariationId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_WITH_PARAMS_VALUE_TYPE(kTestFeature2,
                                              kTestVariations2,
                                              "TestTrial")},
@@ -267,7 +263,8 @@
              // compatible with the current platform.
              {kThirdTestFeatureId, "", "", 0,
               FEATURE_VALUE_TYPE(kTestFeature3)},
-             {kExpiredFlagTestFeatureId, "", "", GetPlatformToUse(),
+             {kExpiredFlagTestFeatureId, "", "",
+              flags_ui::FlagsState::GetCurrentPlatform(),
               FEATURE_VALUE_TYPE(kExpiredFlagTestFeature)}}) {
     // Set expiration milestone such that the flag is expired.
     flags::testing::SetFlagExpiration(kExpiredFlagTestFeatureId, 0);
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.cc b/chrome/browser/ui/web_applications/app_browser_controller.cc
index 4b8b264..054f63e 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller.cc
@@ -393,12 +393,7 @@
 }
 
 bool AppBrowserController::ShouldUseCustomFrame() const {
-#if BUILDFLAG(IS_LINUX)
-  return browser_->profile()->GetPrefs()->GetBoolean(
-      prefs::kUseCustomChromeFrame);
-#else
   return true;
-#endif
 }
 
 void AppBrowserController::AddColorMixers(
diff --git a/chrome/browser/ui/web_applications/web_app_launch_process.cc b/chrome/browser/ui/web_applications/web_app_launch_process.cc
index 6088fa9..25c2d68 100644
--- a/chrome/browser/ui/web_applications/web_app_launch_process.cc
+++ b/chrome/browser/ui/web_applications/web_app_launch_process.cc
@@ -131,8 +131,7 @@
 
 const apps::ShareTarget* WebAppLaunchProcess::MaybeGetShareTarget() const {
   DCHECK(web_app_);
-  bool is_share_intent =
-      params_.intent && apps_util::IsShareIntent(params_.intent);
+  bool is_share_intent = params_.intent && params_.intent->IsShareIntent();
   return is_share_intent && web_app_->share_target().has_value()
              ? &web_app_->share_target().value()
              : nullptr;
@@ -293,9 +292,7 @@
     // TODO(crbug.com/1213776): Expose share target in the LaunchParams and
     // don't navigate if navigate_existing_client: never is in effect.
     NavigateParams nav_params = NavigateParamsForShareTarget(
-        browser, *share_target,
-        *apps::ConvertMojomIntentToIntent(params_.intent),
-        params_.launch_files);
+        browser, *share_target, *params_.intent, params_.launch_files);
     nav_params.disposition = navigation_disposition;
     return {
         .web_contents = NavigateWebAppUsingParams(params_.app_id, nav_params),
diff --git a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
index 27547e1..0d3fc1f 100644
--- a/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
+++ b/chrome/browser/web_applications/app_service/lacros_web_apps_controller.cc
@@ -30,6 +30,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chromeos/lacros/lacros_service.h"
 #include "components/content_settings/core/common/content_settings_pattern.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
@@ -292,7 +293,8 @@
                                              apps::AppLaunchParams params,
                                              CommandFinishedCallback callback) {
   bool is_file_handling_launch =
-      !params.launch_files.empty() && !apps_util::IsShareIntent(params.intent);
+      !params.launch_files.empty() &&
+      !(params.intent && params.intent->IsShareIntent());
   if (is_file_handling_launch) {
     // File handling may create the WebContents asynchronously.
     publisher_helper().LaunchAppWithFilesCheckingUserPermission(
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
index d2f5425f..cfcfc68 100644
--- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
+++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -57,6 +57,7 @@
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/extensions/extension_constants.h"
 #include "components/content_settings/core/common/content_settings.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_filter.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/cpp/publisher_base.h"
diff --git a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
index 36814ace..e1ccad2 100644
--- a/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
+++ b/chrome/browser/web_applications/app_service/web_apps_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chromeos/dbus/cros_disks/cros_disks_client.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "content/public/test/browser_test.h"
@@ -51,7 +52,7 @@
           [&run_loop](apps::AppLaunchParams&& params) -> content::WebContents* {
             EXPECT_EQ(params.intent->action, apps_util::kIntentActionSend);
             EXPECT_EQ(*params.intent->mime_type, "text/csv");
-            EXPECT_EQ(params.intent->files->size(), 1U);
+            EXPECT_EQ(params.intent->files.size(), 1U);
             run_loop.Quit();
             return nullptr;
           }));
@@ -87,7 +88,7 @@
             EXPECT_EQ(params.intent->action,
                       apps_util::kIntentActionSendMultiple);
             EXPECT_EQ(*params.intent->mime_type, "*/*");
-            EXPECT_EQ(params.intent->files->size(), 0U);
+            EXPECT_EQ(params.intent->files.size(), 0U);
             run_loop.Quit();
             return nullptr;
           }));
diff --git a/chrome/browser/web_applications/chrome_pwa_launcher/launcher_update.cc b/chrome/browser/web_applications/chrome_pwa_launcher/launcher_update.cc
index c666697..7c2cd0e 100644
--- a/chrome/browser/web_applications/chrome_pwa_launcher/launcher_update.cc
+++ b/chrome/browser/web_applications/chrome_pwa_launcher/launcher_update.cc
@@ -9,7 +9,6 @@
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
-#include "base/metrics/histogram_functions.h"
 #include "chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.h"
 #include "chrome/installer/util/callback_work_item.h"
 #include "chrome/installer/util/delete_tree_work_item.h"
@@ -20,16 +19,6 @@
 constexpr base::FilePath::StringPieceType kOldLauncherSuffix =
     FILE_PATH_LITERAL("_old");
 
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class WebAppLauncherUpdateResult {
-  kSuccess = 0,
-  kFailedToCreateTempDir = 1,
-  kFailedToReplaceLauncher = 2,
-  kLatestVersionPathDoesNotExist = 3,
-  kMaxValue = kLatestVersionPathDoesNotExist,
-};
-
 // A callback invoked by |work_item| that tries to create a hardlink to
 // |latest_version_path| at |launcher_path|. If it fails, tries to create a copy
 // of |latest_version_path| at |launcher_path| instead. Returns true if either a
@@ -47,10 +36,6 @@
   base::DeleteFile(launcher_path);
 }
 
-void RecordWebAppLauncherUpdateResult(WebAppLauncherUpdateResult result) {
-  base::UmaHistogramEnumeration("WebApp.Launcher.UpdateResult", result);
-}
-
 // Replaces |launcher_path| with the one at |latest_version_path|. This is done
 // by atomically renaming |launcher_path| to |old_path| and creating a hardlink
 // to or copy of |latest_version_path| at |launcher_path|. Makes a best-effort
@@ -59,19 +44,13 @@
 void ReplaceLauncherWithLatestVersion(const base::FilePath& launcher_path,
                                       const base::FilePath& latest_version_path,
                                       const base::FilePath& old_path) {
-  if (!base::PathExists(latest_version_path)) {
-    RecordWebAppLauncherUpdateResult(
-        WebAppLauncherUpdateResult::kLatestVersionPathDoesNotExist);
+  if (!base::PathExists(latest_version_path))
     return;
-  }
 
   // Create a temporary backup directory for use while moving in-use files.
   base::ScopedTempDir temp_dir;
-  if (!temp_dir.CreateUniqueTempDirUnderPath(launcher_path.DirName())) {
-    RecordWebAppLauncherUpdateResult(
-        WebAppLauncherUpdateResult::kFailedToCreateTempDir);
+  if (!temp_dir.CreateUniqueTempDirUnderPath(launcher_path.DirName()))
     return;
-  }
 
   // Move |launcher_path| to |old_path|.
   std::unique_ptr<WorkItemList> change_list(WorkItem::CreateWorkItemList());
@@ -92,13 +71,8 @@
   delete_old_version_work_item->set_rollback_enabled(false);
   change_list->AddWorkItem(delete_old_version_work_item.release());
 
-  if (change_list->Do()) {
-    RecordWebAppLauncherUpdateResult(WebAppLauncherUpdateResult::kSuccess);
-  } else {
+  if (!change_list->Do())
     change_list->Rollback();
-    RecordWebAppLauncherUpdateResult(
-        WebAppLauncherUpdateResult::kFailedToReplaceLauncher);
-  }
 }
 
 // Deletes |old_path| and any variations on it (e.g., |old_path| (1), |old_path|
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 688dcf96..c347984 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1656352780-29b864beabc43da931f35ed5e96ec6730b553ff3.profdata
+chrome-linux-main-1656374249-025b9a78c61a7ecc5e2a07129efab14aece96e69.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 5f0bdca3..29d789d 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1656331133-1941bc675dfd506e6053d4ab5ca07fd9350ca513.profdata
+chrome-mac-arm-main-1656352780-c724ba13f1bf69f0ef8d53992455e3be10040603.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index e2f55039..ea85a492 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1656331133-2a720bfcc444ff205f61e877781c27bf146bd128.profdata
+chrome-mac-main-1656352780-09a2bc005042533490a7648ffea96358e1a35098.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 90cc493..1c9d89e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1656352780-5daf3e33415b6f908ce296574bcb01e54bb545c7.profdata
+chrome-win32-main-1656363454-e6485c4822fbeaa885f9930e030ee7e91388be59.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 4585cb4..a289b5ba 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1656352780-6a26ecd34ca03ea103fa8e994bbbe865a5597d76.profdata
+chrome-win64-main-1656374249-341eac377c618d5d64070621673af33017f76321.profdata
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
index e353690e..216c41e 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -186,6 +186,7 @@
     case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT:
     case extensions::Feature::WEBUI_CONTEXT:
     case extensions::Feature::WEBUI_UNTRUSTED_CONTEXT:
+    case extensions::Feature::OFFSCREEN_EXTENSION_CONTEXT:
     case extensions::Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
       return false;
     case extensions::Feature::BLESSED_EXTENSION_CONTEXT:
@@ -210,6 +211,7 @@
     case extensions::Feature::BLESSED_WEB_PAGE_CONTEXT:
     case extensions::Feature::CONTENT_SCRIPT_CONTEXT:
     case extensions::Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
+    case extensions::Feature::OFFSCREEN_EXTENSION_CONTEXT:
     case extensions::Feature::UNBLESSED_EXTENSION_CONTEXT:
     case extensions::Feature::UNSPECIFIED_CONTEXT:
     case extensions::Feature::WEBUI_CONTEXT:
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 2f8eb3cc..c8d1bab 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2985,6 +2985,7 @@
         "../browser/extensions/mutation_observers_apitest.cc",
         "../browser/extensions/native_bindings_apitest.cc",
         "../browser/extensions/navigation_observer_browsertest.cc",
+        "../browser/extensions/offscreen_document_browsertest.cc",
         "../browser/extensions/options_page_apitest.cc",
         "../browser/extensions/permissions_manager_browsertest.cc",
         "../browser/extensions/preinstalled_apps_browsertest.cc",
@@ -3091,6 +3092,7 @@
           "../browser/chromeos/extensions/accessibility_features_apitest.cc",
           "../browser/chromeos/extensions/action_handlers/action_handlers_apitest.cc",
           "../browser/chromeos/extensions/autotest_private/autotest_private_apitest.cc",
+          "../browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_ash_browsertest.cc",
           "../browser/chromeos/extensions/default_keyboard_extension_browser_test.cc",
           "../browser/chromeos/extensions/default_keyboard_extension_browser_test.h",
           "../browser/chromeos/extensions/echo_private/echo_private_apitest.cc",
@@ -4554,6 +4556,8 @@
     ]
 
     sources = [
+      "../browser/chromeos/extensions/contact_center_insights/contact_center_insights_extension_manager_lacros_browsertest.cc",
+
       # dlp_content_manager_lacros_browsertest.cc should become a unit test.
       "../browser/chromeos/policy/dlp/dlp_content_manager_lacros_browsertest.cc",
       "../browser/chromeos/policy/dlp/dlp_content_manager_test_helper.cc",
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_unload.js b/chrome/test/data/extensions/api_test/webrequest/test_unload.js
index 22f8360..6ea7d86 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_unload.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_unload.js
@@ -17,6 +17,16 @@
   return getServerURL('slow?10', hostname);
 }
 
+function getInitiatorURLForExtension() {
+  var url = getURL('');
+  return url.slice(0, -1);
+}
+
+function getInitiatorURLForHostname(hostname) {
+  var url = getServerURL('', hostname);
+  return url.slice(0, -1);
+}
+
 // Get the URL of a page that inserts a frame with the given URL upon load.
 function getPageWithFrame(frameUrl, hostname) {
   return getServerURL('extensions/api_test/webrequest/unload/load_frame.html?' +
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_unload1.js b/chrome/test/data/extensions/api_test/webrequest/test_unload1.js
index a2b4ad10..2c37a10 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_unload1.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_unload1.js
@@ -19,7 +19,9 @@
           parentFrameId: 0,
           frameUrl: url,
           tabId: 1,
-          initiator: getServerDomain(initiators.BROWSER_INITIATED)
+          initiator: getInitiatorURLForExtension(),
+          parentDocumentId: 1,
+          frameType: 'sub_frame',
         }
       },
       { label: 'onBeforeSendHeaders',
@@ -30,7 +32,9 @@
           frameId: 1,
           parentFrameId: 0,
           tabId: 1,
-          initiator: getServerDomain(initiators.BROWSER_INITIATED)
+          initiator: getInitiatorURLForExtension(),
+          parentDocumentId: 1,
+          frameType: 'sub_frame',
         },
       },
       { label: 'onSendHeaders',
@@ -41,7 +45,9 @@
           frameId: 1,
           parentFrameId: 0,
           tabId: 1,
-          initiator: getServerDomain(initiators.BROWSER_INITIATED)
+          initiator: getInitiatorURLForExtension(),
+          parentDocumentId: 1,
+          frameType: 'sub_frame',
         },
       },
       { label: 'onErrorOccurred',
@@ -54,7 +60,9 @@
           tabId: 1,
           fromCache: false,
           error: 'net::ERR_ABORTED',
-          initiator: getServerDomain(initiators.BROWSER_INITIATED)
+          initiator: getInitiatorURLForExtension(),
+          parentDocumentId: 1,
+          frameType: 'sub_frame',
         },
       }],
       [['onBeforeRequest', 'onBeforeSendHeaders', 'onSendHeaders',
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_unload2.js b/chrome/test/data/extensions/api_test/webrequest/test_unload2.js
index 5d9a3de..5ecfbfe8 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_unload2.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_unload2.js
@@ -14,6 +14,7 @@
           type: 'main_frame',
           url,
           frameUrl: url,
+          initiator: getInitiatorURLForExtension(),
         }
       },
       { label: 'onBeforeSendHeaders',
@@ -21,6 +22,7 @@
         details: {
           type: 'main_frame',
           url,
+          initiator: getInitiatorURLForExtension(),
         },
       },
       { label: 'onSendHeaders',
@@ -28,6 +30,7 @@
         details: {
           type: 'main_frame',
           url,
+          initiator: getInitiatorURLForExtension(),
         },
       },
       { label: 'onErrorOccurred',
@@ -35,6 +38,7 @@
         details: {
           type: 'main_frame',
           url,
+          initiator: getInitiatorURLForExtension(),
           fromCache: false,
           error: 'net::ERR_ABORTED',
         },
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_unload3.js b/chrome/test/data/extensions/api_test/webrequest/test_unload3.js
index e1548d06..758776a 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_unload3.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_unload3.js
@@ -18,6 +18,9 @@
           frameId: 1,
           parentFrameId: 0,
           frameUrl: url,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         }
       },
       { label: 'onBeforeSendHeaders',
@@ -27,6 +30,9 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         },
       },
       { label: 'onSendHeaders',
@@ -36,6 +42,9 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         },
       },
       { label: 'onErrorOccurred',
@@ -45,6 +54,9 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
           fromCache: false,
           error: 'net::ERR_ABORTED',
         },
@@ -81,6 +93,9 @@
           frameId: 1,
           parentFrameId: 0,
           frameUrl: url,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         }
       },
       { label: 'onBeforeSendHeaders',
@@ -90,6 +105,9 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         },
       },
       { label: 'onSendHeaders',
@@ -99,6 +117,9 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         },
       },
       { label: 'onErrorOccurred',
@@ -110,6 +131,9 @@
           parentFrameId: 0,
           fromCache: false,
           error: 'net::ERR_ABORTED',
+          parentDocumentId: 1,
+          initiator: getInitiatorURLForHostname(hostname),
+          frameType: 'sub_frame',
         },
       }],
       [['onBeforeRequest', 'onBeforeSendHeaders', 'onSendHeaders',
diff --git a/chrome/test/data/extensions/api_test/webrequest/test_unload4.js b/chrome/test/data/extensions/api_test/webrequest/test_unload4.js
index 7183498..d884385 100644
--- a/chrome/test/data/extensions/api_test/webrequest/test_unload4.js
+++ b/chrome/test/data/extensions/api_test/webrequest/test_unload4.js
@@ -18,7 +18,13 @@
           frameId: 1,
           parentFrameId: 0,
           frameUrl: 'unknown frame URL',
-        }
+          initiator: getInitiatorURLForHostname(hostname),
+          parentDocumentId: 1,
+          documentId: 2,
+          documentLifecycle: "active",
+          tabId: 0,
+          frameType: "sub_frame",
+         }
       },
       { label: 'onBeforeSendHeaders',
         event: 'onBeforeSendHeaders',
@@ -27,6 +33,12 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          initiator: getInitiatorURLForHostname(hostname),
+          parentDocumentId: 1,
+          documentId: 2,
+          documentLifecycle: "active",
+          tabId: 0,
+          frameType: "sub_frame",
         },
       },
       { label: 'onSendHeaders',
@@ -36,6 +48,12 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          initiator: getInitiatorURLForHostname(hostname),
+          parentDocumentId: 1,
+          documentId: 2,
+          documentLifecycle: "active",
+          tabId: 0,
+          frameType: "sub_frame",
         },
       },
       { label: 'onErrorOccurred',
@@ -45,6 +63,12 @@
           url,
           frameId: 1,
           parentFrameId: 0,
+          initiator: getInitiatorURLForHostname(hostname),
+          parentDocumentId: 1,
+          documentId: 2,
+          documentLifecycle: "active",
+          tabId: 0,
+          frameType: "sub_frame",
           fromCache: false,
           error: 'net::ERR_ABORTED',
         },
@@ -85,29 +109,57 @@
         event: 'onBeforeRequest',
         details: {
           type: 'image',
-          url,
+          url: url,
           frameUrl: 'unknown frame URL',
+          initiator: getInitiatorURLForHostname(hostname),
+          documentId: 1,
+          tabId: 0,
+          frameId: 0,
+          parentFrameId: -1,
+          documentLifecycle: "active",
+          frameType: "outermost_frame"
         }
       },
       { label: 'onBeforeSendHeaders',
         event: 'onBeforeSendHeaders',
         details: {
           type: 'image',
-          url,
+          url: url,
+          initiator: getInitiatorURLForHostname(hostname),
+          documentId: 1,
+          tabId: 0,
+          frameId: 0,
+          parentFrameId: -1,
+          documentLifecycle: "active",
+          frameType: "outermost_frame"
         },
       },
       { label: 'onSendHeaders',
         event: 'onSendHeaders',
         details: {
           type: 'image',
-          url,
+          url: url,
+          initiator: getInitiatorURLForHostname(hostname),
+          documentId: 1,
+          tabId: 0,
+          frameId: 0,
+          parentFrameId: -1,
+          documentLifecycle: "active",
+          frameType: "outermost_frame",
         },
       },
       { label: 'onErrorOccurred',
         event: 'onErrorOccurred',
         details: {
           type: 'image',
-          url,
+          url: url,
+          initiator: getInitiatorURLForHostname(hostname),
+          documentId: 1,
+          tabId: 0,
+          frameId: 0,
+          parentFrameId: -1,
+          documentLifecycle: "active",
+          frameType: "outermost_frame",
           fromCache: false,
           error: 'net::ERR_ABORTED',
         },
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
index c403706..a6cc118 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/confirmation_page_test.js
@@ -98,6 +98,7 @@
     assertEquals(
         'Here are some other helpful resources:',
         getElementContent(page, '#helpResourcesLabel'));
+    assertTrue(page.i18nExists('helpResourcesLabel'));
     const helpLinks = helpResourcesSection.querySelectorAll('cr-link-row');
     assertTrue(!!helpLinks);
     assertEquals(3, helpLinks.length);
@@ -107,11 +108,11 @@
     assertTrue(isVisible(exploreLink));
     assertEquals(
         'help-resources:explore', getElement(exploreLink, '#startIcon').icon);
-    assertEquals('Explore app', getElementContent(exploreLink, '#label'));
+    assertEquals('Explore app', getElementContent(page, '#explore > .label'));
     assertTrue(page.i18nExists('exploreAppLabel'));
     assertEquals(
         'Find help articles and answers to common Chromebook questions',
-        getElementContent(exploreLink, '#subLabel'));
+        getElementContent(page, '#explore > .sub-label'));
     assertTrue(page.i18nExists('exploreAppDescription'));
 
     // Verify the diagnostics app link.
@@ -121,11 +122,11 @@
         'help-resources:diagnostics',
         getElement(diagnosticsLink, '#startIcon').icon);
     assertEquals(
-        'Diagnostics app', getElementContent(diagnosticsLink, '#label'));
+        'Diagnostics app', getElementContent(page, '#diagnostics > .label'));
     assertTrue(page.i18nExists('diagnosticsAppLabel'));
     assertEquals(
         'Run tests and troubleshooting for hardware issues',
-        getElementContent(diagnosticsLink, '#subLabel'));
+        getElementContent(page, '#diagnostics > .sub-label'));
     assertTrue(page.i18nExists('diagnosticsAppDescription'));
 
     // Verify the community link.
@@ -139,10 +140,11 @@
         'help-resources2:chromebook-community',
         getElement(communityLink, '#startIcon').icon);
     assertEquals(
-        'Chromebook community', getElementContent(communityLink, '#label'));
+        'Chromebook community',
+        getElementContent(page, '#chromebookCommunity > .label'));
     assertEquals(
         'Ask the experts in the Chromebook help forum',
-        getElementContent(communityLink, '#subLabel'));
+        getElementContent(page, '#chromebookCommunity > .sub-label'));
     assertTrue(page.i18nExists('askCommunityLabel'));
     assertTrue(page.i18nExists('askCommunityDescription'));
 
diff --git a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
index 8672f33..959994e 100644
--- a/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
+++ b/chrome/test/data/webui/chromeos/os_feedback_ui/help_content_test.js
@@ -102,7 +102,7 @@
         /* isPopularContent= */ true);
 
     // Verify the title is in the helpContentElement.
-    const title = getElement('#helpContentLabel');
+    const title = getElement('.help-content-label');
     assertTrue(!!title);
     assertEquals('Top help content', title.textContent);
 
@@ -119,7 +119,7 @@
         /* isPopularContent =*/ false);
 
     // Verify the title is in the helpContentElement.
-    const title = getElement('#helpContentLabel');
+    const title = getElement('.help-content-label');
     assertTrue(!!title);
     assertEquals('Suggested help content', title.textContent);
 
@@ -175,7 +175,7 @@
         /* isPopularContent= */ true);
 
     // Verify the title is in the helpContentElement.
-    const title = getElement('#helpContentLabel');
+    const title = getElement('.help-content-label');
     assertTrue(!!title);
     assertEquals(
         'No suggested content. See top help content.', title.textContent);
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 9c473b72..23149fdf 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -3456,6 +3456,9 @@
       <message name="IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_DESCRIPTION" desc="Description of the explore app that links to some resourses like help articals and new features of Chromebook.">
         Find help articles and answers to common Chromebook questions
       </message>
+      <message name="IDS_FEEDBACK_TOOL_HELP_RESOURCES_LABEL" desc="Label of some other help resources.">
+        Here are some other helpful resources:
+      </message>
       <message name="IDS_FEEDBACK_TOOL_RESOURCES_EXPLORE_APP_LABEL" desc="Label of the explore app">
         Explore app
       </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_HELP_RESOURCES_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_HELP_RESOURCES_LABEL.png.sha1
new file mode 100644
index 0000000..efe3dc5
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_FEEDBACK_TOOL_HELP_RESOURCES_LABEL.png.sha1
@@ -0,0 +1 @@
+a0d78bdaddc38092118fe47e045d6bea9417232f
\ No newline at end of file
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn
index a08a4ca9..f6b4e83 100644
--- a/chromeos/crosapi/mojom/BUILD.gn
+++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -34,6 +34,7 @@
     "download_controller.mojom",
     "drive_integration_service.mojom",
     "echo_private.mojom",
+    "emoji_picker.mojom",
     "extension_info_private.mojom",
     "feedback.mojom",
     "field_trial.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom
index 2f43385..2701223 100644
--- a/chromeos/crosapi/mojom/crosapi.mojom
+++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -30,6 +30,7 @@
 import "chromeos/crosapi/mojom/download_controller.mojom";
 import "chromeos/crosapi/mojom/drive_integration_service.mojom";
 import "chromeos/crosapi/mojom/echo_private.mojom";
+import "chromeos/crosapi/mojom/emoji_picker.mojom";
 import "chromeos/crosapi/mojom/extension_info_private.mojom";
 import "chromeos/crosapi/mojom/feedback.mojom";
 import "chromeos/crosapi/mojom/field_trial.mojom";
@@ -116,8 +117,8 @@
 // please note the milestone when you added it, to help us reason about
 // compatibility between the client applications and older ash-chrome binaries.
 //
-// Next version: 85
-// Next method id: 88
+// Next version: 86
+// Next method id: 89
 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e",
  RenamedFrom="crosapi.mojom.AshChromeService"]
 interface Crosapi {
@@ -271,6 +272,9 @@
   [MinVersion=71] BindEchoPrivate@74(
       pending_receiver<EchoPrivate> receiver);
 
+  // EmojiPicker is a service to allow lacros to open the system emoji picker.
+  [MinVersion=85] BindEmojiPicker@89(pending_receiver<EmojiPicker> receiver);
+
   // ExtensionInfoPrivate is a service that allows trusted extensions in Lacros
   // to get and set system properties. Implemented in Ash.
   [MinVersion=72] BindExtensionInfoPrivate@75(
diff --git a/chromeos/crosapi/mojom/emoji_picker.mojom b/chromeos/crosapi/mojom/emoji_picker.mojom
new file mode 100644
index 0000000..3aecbcf
--- /dev/null
+++ b/chromeos/crosapi/mojom/emoji_picker.mojom
@@ -0,0 +1,13 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module crosapi.mojom;
+
+// EmojiPicker is an interface to allow lacros to request for the platform
+// specific emoji picker to be opened.
+[Stable, Uuid="b52ff6c9-d8fb-438e-87cf-c6c7aaee3fa6"]
+interface EmojiPicker {
+  // Requests the system emoji picker to be opened.
+  ShowEmojiPicker@0();
+};
\ No newline at end of file
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc
index 2cd137b3..96dde5f 100644
--- a/chromeos/lacros/lacros_service.cc
+++ b/chromeos/lacros/lacros_service.cc
@@ -39,6 +39,7 @@
 #include "chromeos/crosapi/mojom/download_controller.mojom.h"
 #include "chromeos/crosapi/mojom/drive_integration_service.mojom.h"
 #include "chromeos/crosapi/mojom/echo_private.mojom.h"
+#include "chromeos/crosapi/mojom/emoji_picker.mojom.h"
 #include "chromeos/crosapi/mojom/extension_info_private.mojom.h"
 #include "chromeos/crosapi/mojom/feedback.mojom.h"
 #include "chromeos/crosapi/mojom/field_trial.mojom.h"
@@ -289,6 +290,8 @@
   ConstructRemote<crosapi::mojom::EchoPrivate,
                   &crosapi::mojom::Crosapi::BindEchoPrivate,
                   Crosapi::MethodMinVersions::kBindEchoPrivateMinVersion>();
+  ConstructRemote<crosapi::mojom::EmojiPicker, &Crosapi::BindEmojiPicker,
+                  Crosapi::MethodMinVersions::kBindEmojiPickerMinVersion>();
   ConstructRemote<
       crosapi::mojom::ExtensionInfoPrivate,
       &crosapi::mojom::Crosapi::BindExtensionInfoPrivate,
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni
index b5699e89..47b7459 100644
--- a/chromeos/tast_control.gni
+++ b/chromeos/tast_control.gni
@@ -288,9 +288,6 @@
   # http://crbug.com/1335213
   "arc.WindowState.clamshell",
 
-  # http://crbug.com/1337191
-  "platform.Resourced.baseline",
-
   # http://crbug.com/1338201
   "ui.ChromeCrashLoggedIn.gpu_process_breakpad",
 
diff --git a/components/app_restore/app_launch_info.cc b/components/app_restore/app_launch_info.cc
index a33abaff..405be97 100644
--- a/components/app_restore/app_launch_info.cc
+++ b/components/app_restore/app_launch_info.cc
@@ -14,7 +14,7 @@
                              WindowOpenDisposition disposition,
                              int64_t display_id,
                              std::vector<base::FilePath> launch_files,
-                             apps::mojom::IntentPtr intent)
+                             apps::IntentPtr intent)
     : app_id(app_id),
       window_id(window_id),
       container(static_cast<int32_t>(container)),
@@ -31,7 +31,7 @@
                              WindowOpenDisposition disposition,
                              int64_t display_id,
                              std::vector<base::FilePath> launch_files,
-                             apps::mojom::IntentPtr intent)
+                             apps::IntentPtr intent)
     : app_id(app_id),
       container(static_cast<int32_t>(container)),
       disposition(static_cast<int32_t>(disposition)),
@@ -50,7 +50,7 @@
 
 AppLaunchInfo::AppLaunchInfo(const std::string& app_id,
                              int32_t event_flags,
-                             apps::mojom::IntentPtr intent,
+                             apps::IntentPtr intent,
                              int32_t arc_session_id,
                              int64_t display_id)
     : app_id(app_id),
diff --git a/components/app_restore/app_launch_info.h b/components/app_restore/app_launch_info.h
index 2848496..48735886 100644
--- a/components/app_restore/app_launch_info.h
+++ b/components/app_restore/app_launch_info.h
@@ -10,6 +10,7 @@
 #include "base/component_export.h"
 #include "base/files/file_path.h"
 #include "components/app_restore/tab_group_info.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/base/window_open_disposition.h"
@@ -26,7 +27,7 @@
                 WindowOpenDisposition disposition,
                 int64_t display_id,
                 std::vector<base::FilePath> launch_files,
-                apps::mojom::IntentPtr intent);
+                apps::IntentPtr intent);
 
   AppLaunchInfo(const std::string& app_id, int32_t window_id);
 
@@ -35,7 +36,7 @@
                 WindowOpenDisposition disposition,
                 int64_t display_id,
                 std::vector<base::FilePath> launch_files,
-                apps::mojom::IntentPtr intent);
+                apps::IntentPtr intent);
 
   AppLaunchInfo(const std::string& app_id,
                 int32_t event_flags,
@@ -44,7 +45,7 @@
 
   AppLaunchInfo(const std::string& app_id,
                 int32_t event_flags,
-                apps::mojom::IntentPtr intent,
+                apps::IntentPtr intent,
                 int32_t arc_session_id,
                 int64_t display_id);
 
@@ -69,7 +70,7 @@
   absl::optional<std::vector<GURL>> urls;
   absl::optional<int32_t> active_tab_index;
   absl::optional<std::vector<base::FilePath>> file_paths;
-  absl::optional<apps::mojom::IntentPtr> intent;
+  absl::optional<apps::IntentPtr> intent;
   absl::optional<bool> app_type_browser;
   absl::optional<std::string> app_name;
   // For Browsers only, represents tab groups associated with this browser
diff --git a/components/app_restore/app_restore_data.cc b/components/app_restore/app_restore_data.cc
index acaea5a..7aa572b 100644
--- a/components/app_restore/app_restore_data.cc
+++ b/components/app_restore/app_restore_data.cc
@@ -10,6 +10,7 @@
 #include "base/values.h"
 #include "components/app_restore/app_launch_info.h"
 #include "components/app_restore/window_info.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 
 namespace app_restore {
@@ -270,7 +271,8 @@
   urls = std::move(app_launch_info->urls);
   active_tab_index = std::move(app_launch_info->active_tab_index);
   file_paths = std::move(app_launch_info->file_paths);
-  intent = std::move(app_launch_info->intent);
+  if (app_launch_info->intent.has_value() && app_launch_info->intent.value())
+    intent = apps::ConvertIntentToMojomIntent(app_launch_info->intent.value());
   app_type_browser = std::move(app_launch_info->app_type_browser);
   app_name = std::move(app_launch_info->app_name);
   tab_group_infos = std::move(app_launch_info->tab_group_infos);
@@ -529,8 +531,8 @@
   app_launch_info->handler_id = handler_id;
   app_launch_info->urls = urls;
   app_launch_info->file_paths = file_paths;
-  if (intent.has_value())
-    app_launch_info->intent = intent->Clone();
+  if (intent.has_value() && intent.value())
+    app_launch_info->intent = apps::ConvertMojomIntentToIntent(intent.value());
   app_launch_info->app_type_browser = app_type_browser;
   app_launch_info->app_name = app_name;
   app_launch_info->tab_group_infos = tab_group_infos;
diff --git a/components/app_restore/full_restore_read_and_save_unittest.cc b/components/app_restore/full_restore_read_and_save_unittest.cc
index 132be9d9..c59c981 100644
--- a/components/app_restore/full_restore_read_and_save_unittest.cc
+++ b/components/app_restore/full_restore_read_and_save_unittest.cc
@@ -23,6 +23,8 @@
 #include "components/app_restore/restore_data.h"
 #include "components/app_restore/window_info.h"
 #include "components/app_restore/window_properties.h"
+#include "components/services/app_service/public/cpp/intent.h"
+#include "components/services/app_service/public/cpp/intent_util.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "content/public/test/browser_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -1114,7 +1116,7 @@
   base::OneShotTimer* timer = save_handler->GetTimerForTesting();
 
   // Add a Chrome app launch info.
-  auto intent = apps::mojom::Intent::New();
+  auto intent = std::make_unique<apps::Intent>(apps_util::kIntentActionSend);
   intent->activity_name = "activity_name";
   SaveAppLaunchInfo(
       GetPath(),
diff --git a/components/app_restore/restore_data_unittest.cc b/components/app_restore/restore_data_unittest.cc
index 77fa3f0..259205f 100644
--- a/components/app_restore/restore_data_unittest.cc
+++ b/components/app_restore/restore_data_unittest.cc
@@ -15,6 +15,7 @@
 #include "components/app_restore/app_restore_data.h"
 #include "components/app_restore/tab_group_info.h"
 #include "components/app_restore/window_info.h"
+#include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
 #include "components/tab_groups/tab_group_color.h"
 #include "components/tab_groups/tab_group_visual_data.h"
@@ -135,6 +136,16 @@
   RestoreDataTest& operator=(const RestoreDataTest&) = delete;
   ~RestoreDataTest() override = default;
 
+  apps::IntentPtr MakeIntent(const std::string& action,
+                             const std::string& mime_type,
+                             const std::string& share_text) {
+    auto intent = std::make_unique<apps::Intent>(action);
+    intent->mime_type = mime_type;
+    intent->share_text = share_text;
+    return intent;
+  }
+
+  // TODO(crbug.com/1253250): Remove and use the non mojom intent.
   apps::mojom::IntentPtr CreateIntent(const std::string& action,
                                       const std::string& mime_type,
                                       const std::string& share_text) {
@@ -153,7 +164,7 @@
             WindowOpenDisposition::NEW_WINDOW, kDisplayId1,
             std::vector<base::FilePath>{base::FilePath(kFilePath1),
                                         base::FilePath(kFilePath2)},
-            CreateIntent(kIntentActionSend, kMimeType, kShareText1));
+            MakeIntent(kIntentActionSend, kMimeType, kShareText1));
 
     std::unique_ptr<AppLaunchInfo> app_launch_info2 =
         std::make_unique<AppLaunchInfo>(
@@ -161,7 +172,7 @@
             apps::mojom::LaunchContainer::kLaunchContainerTab,
             WindowOpenDisposition::NEW_FOREGROUND_TAB, kDisplayId2,
             std::vector<base::FilePath>{base::FilePath(kFilePath2)},
-            CreateIntent(kIntentActionView, kMimeType, kShareText2));
+            MakeIntent(kIntentActionView, kMimeType, kShareText2));
     app_launch_info2->app_type_browser = kAppTypeBrower2;
     app_launch_info2->tab_group_infos.emplace();
     PopulateTestTabgroups(app_launch_info2->tab_group_infos.value());
@@ -172,7 +183,7 @@
             apps::mojom::LaunchContainer::kLaunchContainerNone,
             WindowOpenDisposition::NEW_POPUP, kDisplayId2,
             std::vector<base::FilePath>{base::FilePath(kFilePath1)},
-            CreateIntent(kIntentActionView, kMimeType, kShareText1));
+            MakeIntent(kIntentActionView, kMimeType, kShareText1));
 
     restore_data().AddAppLaunchInfo(std::move(app_launch_info1));
     restore_data().AddAppLaunchInfo(std::move(app_launch_info2));
diff --git a/components/autofill/core/browser/ui/suggestion.h b/components/autofill/core/browser/ui/suggestion.h
index ad9eb789..7216790b 100644
--- a/components/autofill/core/browser/ui/suggestion.h
+++ b/components/autofill/core/browser/ui/suggestion.h
@@ -75,9 +75,23 @@
 
   template <typename T>
   T GetPayload() const {
+#if DCHECK_IS_ON()
+    DCHECK(Invariant());
+#endif
     return absl::holds_alternative<T>(payload) ? absl::get<T>(payload) : T{};
   }
 
+#if DCHECK_IS_ON()
+  bool Invariant() const {
+    switch (frontend_id) {
+      case PopupItemId::POPUP_ITEM_ID_SEE_PROMO_CODE_DETAILS:
+        return absl::holds_alternative<GURL>(payload);
+      default:
+        return absl::holds_alternative<std::string>(payload);
+    }
+  }
+#endif
+
   // Payload generated by the backend layer. This payload is either a GUID that
   // identifies the exact autofill profile that generated this suggestion, or a
   // GURL that the suggestion should navigate to upon being accepted.
diff --git a/components/bookmarks/browser/url_index.cc b/components/bookmarks/browser/url_index.cc
index 033f5a5e3..a215100 100644
--- a/components/bookmarks/browser/url_index.cc
+++ b/components/bookmarks/browser/url_index.cc
@@ -144,9 +144,12 @@
       bookmarks_with_same_url.clear();
     }
 
+    stats.avg_num_days_since_added +=
+        (base::Time::Now() - (*i)->date_added()).InDays();
     bookmarks_with_same_url.push_back(*i);
   }
 
+  stats.avg_num_days_since_added /= nodes_ordered_by_url_set_.size();
   AddStatsForBookmarksWithSameUrl(&bookmarks_with_same_url, &stats);
   return stats;
 }
diff --git a/components/bookmarks/common/bookmark_metrics.cc b/components/bookmarks/common/bookmark_metrics.cc
index 40f6ef0..abeab935 100644
--- a/components/bookmarks/common/bookmark_metrics.cc
+++ b/components/bookmarks/common/bookmark_metrics.cc
@@ -72,6 +72,9 @@
       base::saturated_cast<int>(
           stats.total_url_bookmark_count -
           stats.duplicate_url_and_title_and_parent_bookmark_count));
+  base::UmaHistogramCounts1000(
+      "Bookmarks.Times.OnProfileLoad.TimeSinceAdded",
+      base::saturated_cast<int>(stats.avg_num_days_since_added));
 }
 
 }  // namespace bookmarks::metrics
\ No newline at end of file
diff --git a/components/bookmarks/common/url_load_stats.h b/components/bookmarks/common/url_load_stats.h
index a3964cd..3377c11 100644
--- a/components/bookmarks/common/url_load_stats.h
+++ b/components/bookmarks/common/url_load_stats.h
@@ -23,6 +23,8 @@
   // parent> that is used by at least one other bookmark, excluding one
   // bookmark per unique URL (i.e. all except one are considered duplicates).
   size_t duplicate_url_and_title_and_parent_bookmark_count = 0;
+  // Average number of days since each bookmark was added.
+  size_t avg_num_days_since_added = 0;
 };
 
 }  // namespace bookmarks
diff --git a/components/browser_ui/strings/android/browser_ui_strings.grd b/components/browser_ui/strings/android/browser_ui_strings.grd
index 15a2ed9..aaea654 100644
--- a/components/browser_ui/strings/android/browser_ui_strings.grd
+++ b/components/browser_ui/strings/android/browser_ui_strings.grd
@@ -262,9 +262,6 @@
       <message name="IDS_ADD" desc="Prompt for the user to add something, like a new address. [CHAR_LIMIT=20]">
         Add
       </message>
-      <message name="IDS_CHANGE" desc="Prompt for the user to change something. [CHAR_LIMIT=20]">
-        Change
-      </message>
       <message name="IDS_SHARE" desc="Content description for a button to share item(s). [CHAR_LIMIT=20]">
         Share
       </message>
diff --git a/components/browsing_topics/browsing_topics_calculator_unittest.cc b/components/browsing_topics/browsing_topics_calculator_unittest.cc
index 8b9b498..a693372 100644
--- a/components/browsing_topics/browsing_topics_calculator_unittest.cc
+++ b/components/browsing_topics/browsing_topics_calculator_unittest.cc
@@ -85,7 +85,8 @@
     page_content_annotations_service_ =
         std::make_unique<optimization_guide::PageContentAnnotationsService>(
             "en-US", optimization_guide_model_provider_.get(),
-            history_service_.get(), nullptr, base::FilePath(), nullptr);
+            history_service_.get(), nullptr, base::FilePath(), nullptr,
+            nullptr);
 
     page_content_annotations_service_->OverridePageContentAnnotatorForTesting(
         &test_page_content_annotator_);
diff --git a/components/browsing_topics/browsing_topics_service_impl_unittest.cc b/components/browsing_topics/browsing_topics_service_impl_unittest.cc
index b79fd58c4..822dd01 100644
--- a/components/browsing_topics/browsing_topics_service_impl_unittest.cc
+++ b/components/browsing_topics/browsing_topics_service_impl_unittest.cc
@@ -187,7 +187,8 @@
     page_content_annotations_service_ =
         std::make_unique<optimization_guide::PageContentAnnotationsService>(
             "en-US", optimization_guide_model_provider_.get(),
-            history_service_.get(), nullptr, base::FilePath(), nullptr);
+            history_service_.get(), nullptr, base::FilePath(), nullptr,
+            nullptr);
 
     page_content_annotations_service_->OverridePageContentAnnotatorForTesting(
         &test_page_content_annotator_);
diff --git a/components/desks_storage/core/desk_template_conversion_unittests.cc b/components/desks_storage/core/desk_template_conversion_unittests.cc
index 8051cfe..45db2233 100644
--- a/components/desks_storage/core/desk_template_conversion_unittests.cc
+++ b/components/desks_storage/core/desk_template_conversion_unittests.cc
@@ -42,57 +42,6 @@
     "7f4b7ff0-970a-41bb-aa91-f6c3e2724207";
 const std::string kBrowserTemplateName = "BrowserTest";
 const std::string kChromePwaTemplateName = "ChromeAppTest";
-const std::string kValidTemplateBrowser =
-    "{\"version\":1,\"uuid\":\"" + kTestUuidBrowser + "\",\"name\":\"" +
-    kBrowserTemplateName +
-    "\",\"created_time_usec\":\"1633535632\",\"updated_time_usec\": "
-    "\"1633535632\",\"desk_type\":\"TEMPLATE\",\"desk\":{\"apps\":[{\"window_"
-    "bound\":{\"left\":0,\"top\":1,\"height\":121,\"width\":120},\"window_"
-    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"BROWSER\",\"tabs\":[{"
-    "\"url\":\"" +
-    kBrowserUrl1 +
-    "\"},{\"url\":\"https://"
-    "example.com/"
-    "2\"}],\"tab_groups\":[{\"first_"
-    "index\":1,\"last_index\":2,\"title\":\"sample_tab_"
-    "group\",\"color\":\"GREY\",\"is_collapsed\":false}],\"active_tab_index\":"
-    "1,\"window_id\":0,"
-    "\"display_id\":\"100\",\"event_flag\":0,\"pre_minimized_window_state\":"
-    "\"NORMAL\"}]}}";
-const std::string kValidTemplateChromeAndProgressive =
-    "{\"version\":1,\"uuid\":\"" + kTestUuidChromeAndProgressive +
-    "\",\"name\":\"" + kChromePwaTemplateName +
-    "\",\"created_time_usec\":\"1633535632000\",\"updated_time_usec\": "
-    "\"1633535632\",\"desk_type\":\"SAVE_AND_RECALL\",\"desk\":{\"apps\":[{"
-    "\"window_"
-    "bound\":{"
-    "\"left\":200,\"top\":200,\"height\":1000,\"width\":1000},\"window_state\":"
-    "\"PRIMARY_SNAPPED\",\"z_index\":2,\"app_type\":\"CHROME_APP\",\"app_id\":"
-    "\"" +
-    desk_test_util::kTestChromeAppId1 +
-    "\",\"window_id\":0,\"display_id\":\"100\",\"event_flag\":0,\"pre_"
-    "minimized_window_state\":\"NORMAL\", \"snap_percent\":75},{\"window_"
-    "bound\":{\"left\":0,\"top\":0,\"height\":120,\"width\":120},\"window_"
-    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"CHROME_APP\",\"app_id\":"
-    "\"" +
-    desk_test_util::kTestPwaAppId1 +
-    "\",\"window_id\":1,\"display_id\":"
-    "\"100\",\"event_flag\":0,\"pre_minimized_window_state\":\"NORMAL\"}]}}";
-const std::string kTemplateWithoutType =
-    "{\"version\":1,\"uuid\":\"" + kTestUuidBrowser + "\",\"name\":\"" +
-    kBrowserTemplateName +
-    "\",\"created_time_usec\":\"1633535632\",\"updated_time_usec\": "
-    "\"1633535632\",\"desk\":{\"apps\":[{\"window_"
-    "bound\":{\"left\":0,\"top\":1,\"height\":121,\"width\":120},\"window_"
-    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"BROWSER\",\"tabs\":[{"
-    "\"url\":\"" +
-    kBrowserUrl1 + "\"},{\"url\":\"" + kBrowserUrl1 +
-    "\"}],\"tab_groups\":[{\"first_"
-    "index\":1,\"last_index\":2,\"title\":\"sample_tab_"
-    "group\",\"color\":\"GREY\",\"is_collapsed\":false}],\"active_tab_index\":"
-    "1,\"window_id\":0,"
-    "\"display_id\":\"100\",\"event_flag\":0,\"pre_minimized_window_state\":"
-    "\"NORMAL\"}]}}";
 const constexpr char16_t kSampleTabGroupTitle[] = u"sample_tab_group";
 
 app_restore::TabGroupInfo MakeSampleTabGroup() {
@@ -125,7 +74,8 @@
 };
 
 TEST_F(DeskTemplateConversionTest, ParseBrowserTemplate) {
-  base::StringPiece raw_json = base::StringPiece(kValidTemplateBrowser);
+  base::StringPiece raw_json =
+      base::StringPiece(desk_test_util::kValidPolicyTemplateBrowser);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
@@ -183,8 +133,8 @@
 }
 
 TEST_F(DeskTemplateConversionTest, ParseChromePwaTemplate) {
-  base::StringPiece raw_json =
-      base::StringPiece(kValidTemplateChromeAndProgressive);
+  base::StringPiece raw_json = base::StringPiece(
+      desk_test_util::kValidPolicyTemplateChromeAndProgressive);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
@@ -283,7 +233,8 @@
 }
 
 TEST_F(DeskTemplateConversionTest, ParsesWithDefaultValueSetToTemplates) {
-  base::StringPiece raw_json = base::StringPiece(kTemplateWithoutType);
+  base::StringPiece raw_json =
+      base::StringPiece(desk_test_util::kPolicyTemplateWithoutType);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
@@ -297,7 +248,8 @@
 }
 
 TEST_F(DeskTemplateConversionTest, DeskTemplateFromJsonBrowserTest) {
-  base::StringPiece raw_json = base::StringPiece(kValidTemplateBrowser);
+  base::StringPiece raw_json =
+      base::StringPiece(desk_test_util::kValidPolicyTemplateBrowser);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
@@ -318,7 +270,8 @@
 }
 
 TEST_F(DeskTemplateConversionTest, ToJsonIgnoreUnsupportedApp) {
-  base::StringPiece raw_json = base::StringPiece(kValidTemplateBrowser);
+  base::StringPiece raw_json =
+      base::StringPiece(desk_test_util::kValidPolicyTemplateBrowser);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
@@ -344,8 +297,8 @@
 }
 
 TEST_F(DeskTemplateConversionTest, DeskTemplateFromJsonAppTest) {
-  base::StringPiece raw_json =
-      base::StringPiece(kValidTemplateChromeAndProgressive);
+  base::StringPiece raw_json = base::StringPiece(
+      desk_test_util::kValidPolicyTemplateChromeAndProgressive);
   auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(raw_json);
 
   EXPECT_TRUE(parsed_json.has_value());
diff --git a/components/desks_storage/core/desk_test_util.h b/components/desks_storage/core/desk_test_util.h
index 34be746..4c7718a96 100644
--- a/components/desks_storage/core/desk_test_util.h
+++ b/components/desks_storage/core/desk_test_util.h
@@ -8,9 +8,18 @@
 #include "components/account_id/account_id.h"
 #include "components/services/app_service/public/cpp/app_registry_cache.h"
 
-namespace desks_storage {
+namespace {
 
-namespace desk_test_util {
+const std::string kTestUuidBrowser = "040b6112-67f2-4d3c-8ba8-53a117272eba";
+const std::string kBrowserUrl = "https://example.com/";
+const std::string kTestUuidChromeAndProgressive =
+    "7f4b7ff0-970a-41bb-aa91-f6c3e2724207";
+const std::string kBrowserTemplateName = "BrowserTest";
+const std::string kChromePwaTemplateName = "ChromeAppTest";
+
+}  // namespace
+
+namespace desks_storage::desk_test_util {
 
 constexpr char kTestChromeAppId[] = "test_chrome_app_id";
 constexpr char kTestPwaAppId[] = "test_pwa_app_id";
@@ -21,6 +30,60 @@
 constexpr char kTestChromeAppId1[] = "test_chrome_app_1";
 constexpr char kTestPwaAppId1[] = "test_pwa_app_1";
 
+const std::string kValidPolicyTemplateBrowser =
+    "{\"version\":1,\"uuid\":\"" + kTestUuidBrowser + "\",\"name\":\"" +
+    kBrowserTemplateName +
+    "\",\"created_time_usec\":\"1633535632\",\"updated_time_usec\": "
+    "\"1633535632\",\"desk_type\":\"TEMPLATE\",\"desk\":{\"apps\":[{\"window_"
+    "bound\":{\"left\":0,\"top\":1,\"height\":121,\"width\":120},\"window_"
+    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"BROWSER\",\"tabs\":[{"
+    "\"url\":\"" +
+    kBrowserUrl +
+    "\"},{\"url\":\"https://"
+    "example.com/"
+    "2\"}],\"tab_groups\":[{\"first_"
+    "index\":1,\"last_index\":2,\"title\":\"sample_tab_"
+    "group\",\"color\":\"GREY\",\"is_collapsed\":false}],\"active_tab_index\":"
+    "1,\"window_id\":0,"
+    "\"display_id\":\"100\",\"event_flag\":0,\"pre_minimized_window_state\":"
+    "\"NORMAL\"}]}}";
+
+const std::string kValidPolicyTemplateChromeAndProgressive =
+    "{\"version\":1,\"uuid\":\"" + kTestUuidChromeAndProgressive +
+    "\",\"name\":\"" + kChromePwaTemplateName +
+    "\",\"created_time_usec\":\"1633535632000\",\"updated_time_usec\": "
+    "\"1633535632\",\"desk_type\":\"SAVE_AND_RECALL\",\"desk\":{\"apps\":[{"
+    "\"window_"
+    "bound\":{"
+    "\"left\":200,\"top\":200,\"height\":1000,\"width\":1000},\"window_state\":"
+    "\"PRIMARY_SNAPPED\",\"z_index\":2,\"app_type\":\"CHROME_APP\",\"app_id\":"
+    "\"" +
+    desk_test_util::kTestChromeAppId1 +
+    "\",\"window_id\":0,\"display_id\":\"100\",\"event_flag\":0,\"pre_"
+    "minimized_window_state\":\"NORMAL\", \"snap_percent\":75},{\"window_"
+    "bound\":{\"left\":0,\"top\":0,\"height\":120,\"width\":120},\"window_"
+    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"CHROME_APP\",\"app_id\":"
+    "\"" +
+    desk_test_util::kTestPwaAppId1 +
+    "\",\"window_id\":1,\"display_id\":"
+    "\"100\",\"event_flag\":0,\"pre_minimized_window_state\":\"NORMAL\"}]}}";
+
+const std::string kPolicyTemplateWithoutType =
+    "{\"version\":1,\"uuid\":\"" + kTestUuidBrowser + "\",\"name\":\"" +
+    kBrowserTemplateName +
+    "\",\"created_time_usec\":\"1633535632\",\"updated_time_usec\": "
+    "\"1633535632\",\"desk\":{\"apps\":[{\"window_"
+    "bound\":{\"left\":0,\"top\":1,\"height\":121,\"width\":120},\"window_"
+    "state\":\"NORMAL\",\"z_index\":1,\"app_type\":\"BROWSER\",\"tabs\":[{"
+    "\"url\":\"" +
+    kBrowserUrl + "\"},{\"url\":\"" + kBrowserUrl +
+    "\"}],\"tab_groups\":[{\"first_"
+    "index\":1,\"last_index\":2,\"title\":\"sample_tab_"
+    "group\",\"color\":\"GREY\",\"is_collapsed\":false}],\"active_tab_index\":"
+    "1,\"window_id\":0,"
+    "\"display_id\":\"100\",\"event_flag\":0,\"pre_minimized_window_state\":"
+    "\"NORMAL\"}]}}";
+
 // Populates the given cache with test app information.
 void PopulateAppRegistryCache(AccountId account_id,
                               apps::AppRegistryCache* cache);
@@ -29,8 +92,6 @@
                                 apps::AppRegistryCache* cache,
                                 const char* app_id);
 
-}  // namespace desk_test_util
-
-}  // namespace desks_storage
+}  // namespace desks_storage::desk_test_util
 
 #endif  // COMPONENTS_DESKS_STORAGE_CORE_DESK_TEST_UTIL_H_
diff --git a/components/exo/text_input.cc b/components/exo/text_input.cc
index db5c088..78bde60 100644
--- a/components/exo/text_input.cc
+++ b/components/exo/text_input.cc
@@ -130,9 +130,9 @@
   // user has a selection, then we can assume the min value of the cursor_pos
   // range as the start of the composition, as the selection will be replaced
   // by the composition text being set.
-  uint32_t composition_start = composition_range_.IsValid()
-                                   ? composition_range_.GetMin()
-                                   : cursor_pos_.GetMin();
+  size_t composition_start = cursor_pos_.IsValid() ? cursor_pos_.GetMin() : 0;
+  if (composition_range_.IsValid())
+    composition_start = composition_range_.GetMin();
   composition_range_ = gfx::Range(composition_start,
                                   composition_start + composition.text.size());
   delegate_->SetCompositionText(composition);
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentAggregatorBridge.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentAggregatorBridge.java
index cc8a438..7606cb5 100644
--- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentAggregatorBridge.java
+++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentAggregatorBridge.java
@@ -77,17 +77,6 @@
     }
 
     @Override
-    public void changeSchedule(final ContentId id, final OfflineItemSchedule schedule) {
-        if (mNativeOfflineContentAggregatorBridge == 0) return;
-        boolean onlyOnWifi = (schedule == null) ? false : schedule.onlyOnWifi;
-        long startTimeMs = (schedule == null) ? -1 : schedule.startTimeMs;
-
-        OfflineContentAggregatorBridgeJni.get().changeSchedule(
-                mNativeOfflineContentAggregatorBridge, OfflineContentAggregatorBridge.this,
-                id.namespace, id.id, onlyOnWifi, startTimeMs);
-    }
-
-    @Override
     public void getItemById(ContentId id, Callback<OfflineItem> callback) {
         if (mNativeOfflineContentAggregatorBridge == 0) return;
         OfflineContentAggregatorBridgeJni.get().getItemById(mNativeOfflineContentAggregatorBridge,
@@ -220,8 +209,5 @@
         void renameItem(long nativeOfflineContentAggregatorBridge,
                 OfflineContentAggregatorBridge caller, String nameSpace, String id, String name,
                 Callback</*RenameResult*/ Integer> callback);
-        void changeSchedule(long nativeOfflineContentAggregatorBridge,
-                OfflineContentAggregatorBridge caller, String nameSpace, String id,
-                boolean onlyOnWifi, long startTimeMs);
     }
 }
diff --git a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentProvider.java b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentProvider.java
index 45d5f2c..f6a1661 100644
--- a/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentProvider.java
+++ b/components/offline_items_collection/core/android/java/src/org/chromium/components/offline_items_collection/OfflineContentProvider.java
@@ -44,9 +44,6 @@
     /** See OfflineContentProvider::ResumeDownload(...). */
     void resumeDownload(ContentId id, boolean hasUserGesture);
 
-    /** See OfflineContentProvider::ChangeSchedule(...). */
-    void changeSchedule(final ContentId id, final OfflineItemSchedule schedule);
-
     /** See OfflineContentProvider::GetItemById(...). */
     void getItemById(ContentId id, Callback<OfflineItem> callback);
 
diff --git a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
index aa422c1..789346c 100644
--- a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
+++ b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.cc
@@ -249,26 +249,6 @@
                         std::move(callback));
 }
 
-void OfflineContentAggregatorBridge::ChangeSchedule(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& jobj,
-    const base::android::JavaParamRef<jstring>& j_namespace,
-    const base::android::JavaParamRef<jstring>& j_id,
-    jboolean j_only_on_wifi,
-    jlong j_start_time_ms) {
-  absl::optional<OfflineItemSchedule> schedule;
-  if (j_only_on_wifi)
-    schedule = absl::make_optional<OfflineItemSchedule>(true, absl::nullopt);
-  else if (j_start_time_ms > 0) {
-    schedule = absl::make_optional<OfflineItemSchedule>(
-        false, base::Time::FromJavaTime(j_start_time_ms));
-  }
-
-  provider_->ChangeSchedule(JNI_OfflineContentAggregatorBridge_CreateContentId(
-                                env, j_namespace, j_id),
-                            std::move(schedule));
-}
-
 void OfflineContentAggregatorBridge::OnItemsAdded(
     const OfflineContentProvider::OfflineItemList& items) {
   if (java_ref_.is_null())
diff --git a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
index fb094c2..2febaf7 100644
--- a/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
+++ b/components/offline_items_collection/core/android/offline_content_aggregator_bridge.h
@@ -92,13 +92,6 @@
                   const base::android::JavaParamRef<jstring>& j_name,
                   const base::android::JavaParamRef<jobject>& j_callback);
 
-  void ChangeSchedule(JNIEnv* env,
-                      const base::android::JavaParamRef<jobject>& jobj,
-                      const base::android::JavaParamRef<jstring>& j_namespace,
-                      const base::android::JavaParamRef<jstring>& j_id,
-                      jboolean j_only_on_wifi,
-                      jlong j_start_time_ms);
-
  private:
   OfflineContentAggregatorBridge(OfflineContentAggregator* aggregator);
 
diff --git a/components/offline_items_collection/core/offline_content_aggregator.cc b/components/offline_items_collection/core/offline_content_aggregator.cc
index 9741f84d..21aba2b 100644
--- a/components/offline_items_collection/core/offline_content_aggregator.cc
+++ b/components/offline_items_collection/core/offline_content_aggregator.cc
@@ -233,16 +233,6 @@
   it->second->RenameItem(id, name, std::move(callback));
 }
 
-void OfflineContentAggregator::ChangeSchedule(
-    const ContentId& id,
-    absl::optional<OfflineItemSchedule> schedule) {
-  auto it = providers_.find(id.name_space);
-  if (it == providers_.end())
-    return;
-
-  it->second->ChangeSchedule(id, std::move(schedule));
-}
-
 void OfflineContentAggregator::OnItemsAdded(const OfflineItemList& items) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   NotifyItemsAdded(items);
diff --git a/components/offline_items_collection/core/offline_content_aggregator.h b/components/offline_items_collection/core/offline_content_aggregator.h
index 309da5a..b13b9ec 100644
--- a/components/offline_items_collection/core/offline_content_aggregator.h
+++ b/components/offline_items_collection/core/offline_content_aggregator.h
@@ -84,8 +84,6 @@
   void RenameItem(const ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(const ContentId& id,
-                      absl::optional<OfflineItemSchedule> schedule) override;
 
  private:
   // OfflineContentProvider::Observer implementation.
diff --git a/components/offline_items_collection/core/offline_content_provider.h b/components/offline_items_collection/core/offline_content_provider.h
index aefc009..08e4348 100644
--- a/components/offline_items_collection/core/offline_content_provider.h
+++ b/components/offline_items_collection/core/offline_content_provider.h
@@ -21,7 +21,6 @@
 
 struct ContentId;
 struct OfflineItem;
-struct OfflineItemSchedule;
 struct OfflineItemShareInfo;
 struct OfflineItemVisuals;
 
@@ -159,10 +158,6 @@
                           const std::string& name,
                           RenameCallback callback) = 0;
 
-  // Called to change when to start the OfflineItem represented by |id|.
-  virtual void ChangeSchedule(const ContentId& id,
-                              absl::optional<OfflineItemSchedule> schedule) = 0;
-
   // Adds an observer that should be notified of OfflineItem list modifications.
   void AddObserver(Observer* observer);
 
diff --git a/components/offline_items_collection/core/test_support/mock_offline_content_provider.h b/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
index 582db0b..a59c970 100644
--- a/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
+++ b/components/offline_items_collection/core/test_support/mock_offline_content_provider.h
@@ -60,10 +60,6 @@
   void GetItemById(const ContentId& id, SingleItemCallback callback) override;
   MOCK_METHOD3(RenameItem,
                void(const ContentId&, const std::string&, RenameCallback));
-  MOCK_METHOD(void,
-              ChangeSchedule,
-              (const ContentId&, absl::optional<OfflineItemSchedule>),
-              (override));
 
  private:
   OfflineItemList items_;
diff --git a/components/offline_items_collection/core/throttled_offline_content_provider.cc b/components/offline_items_collection/core/throttled_offline_content_provider.cc
index 6a1eef7a..2076edd 100644
--- a/components/offline_items_collection/core/throttled_offline_content_provider.cc
+++ b/components/offline_items_collection/core/throttled_offline_content_provider.cc
@@ -111,12 +111,6 @@
   wrapped_provider_->RenameItem(id, name, std::move(callback));
 }
 
-void ThrottledOfflineContentProvider::ChangeSchedule(
-    const ContentId& id,
-    absl::optional<OfflineItemSchedule> schedule) {
-  wrapped_provider_->ChangeSchedule(id, std::move(schedule));
-}
-
 void ThrottledOfflineContentProvider::OnItemsAdded(
     const OfflineItemList& items) {
   NotifyItemsAdded(items);
diff --git a/components/offline_items_collection/core/throttled_offline_content_provider.h b/components/offline_items_collection/core/throttled_offline_content_provider.h
index 8c9f834a..b12eeae 100644
--- a/components/offline_items_collection/core/throttled_offline_content_provider.h
+++ b/components/offline_items_collection/core/throttled_offline_content_provider.h
@@ -61,8 +61,6 @@
   void RenameItem(const ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(const ContentId& id,
-                      absl::optional<OfflineItemSchedule> schedule) override;
 
   // Visible for testing. Overrides the time at which this throttle last pushed
   // updates to observers.
diff --git a/components/offline_pages/core/downloads/download_ui_adapter.cc b/components/offline_pages/core/downloads/download_ui_adapter.cc
index e798ffd2..bd83ec0 100644
--- a/components/offline_pages/core/downloads/download_ui_adapter.cc
+++ b/components/offline_pages/core/downloads/download_ui_adapter.cc
@@ -231,12 +231,6 @@
   NOTREACHED();
 }
 
-void DownloadUIAdapter::ChangeSchedule(
-    const ContentId& id,
-    absl::optional<OfflineItemSchedule> schedule) {
-  NOTREACHED();
-}
-
 void DownloadUIAdapter::OnPageGetForVisuals(
     const ContentId& id,
     GetVisualsOptions options,
diff --git a/components/offline_pages/core/downloads/download_ui_adapter.h b/components/offline_pages/core/downloads/download_ui_adapter.h
index 4db4fbc..c7ddbb30 100644
--- a/components/offline_pages/core/downloads/download_ui_adapter.h
+++ b/components/offline_pages/core/downloads/download_ui_adapter.h
@@ -108,8 +108,6 @@
   void RenameItem(const ContentId& id,
                   const std::string& name,
                   RenameCallback callback) override;
-  void ChangeSchedule(const ContentId& id,
-                      absl::optional<OfflineItemSchedule> schedule) override;
 
   // OfflinePageModel::Observer
   void OfflinePageModelLoaded(OfflinePageModel* model) override;
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc
index 244695b1..41c59e6e 100644
--- a/components/omnibox/browser/autocomplete_classifier.cc
+++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -47,6 +47,9 @@
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
       // Custom search engines cannot be used on mobile.
       AutocompleteProvider::TYPE_KEYWORD |
+      (OmniboxFieldTrial::IsSiteSearchStarterPackEnabled()
+           ? AutocompleteProvider::TYPE_OPEN_TAB
+           : 0) |
 #else
       AutocompleteProvider::TYPE_CLIPBOARD |
       AutocompleteProvider::TYPE_MOST_VISITED_SITES |
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index b0a0a51..582bf7c2 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -34,6 +34,7 @@
 #include "components/history_clusters/core/config.h"
 #include "components/omnibox/browser/actions/omnibox_pedal_provider.h"
 #include "components/omnibox/browser/autocomplete_input.h"
+#include "components/omnibox/browser/autocomplete_provider.h"
 #include "components/omnibox/browser/bookmark_provider.h"
 #include "components/omnibox/browser/builtin_provider.h"
 #include "components/omnibox/browser/clipboard_provider.h"
@@ -480,7 +481,10 @@
   // if we run all providers.
   in_start_ = true;
   base::TimeTicks start_time = base::TimeTicks::Now();
-  for (const auto& provider : GetProvidersToRun()) {
+  for (const auto& provider : providers_) {
+    if (!ShouldRunProvider(provider.get()))
+      continue;
+
     base::TimeTicks provider_start_time = base::TimeTicks::Now();
     provider->Start(input_, minimal_changes);
     if (!input.want_asynchronous_matches())
@@ -558,10 +562,10 @@
     return;
   }
 
-  // Starter Pack engines in keyword mode only run a subset of the providers, so
-  // call `GetProvidersToRun()` to determine the subset or if we run all
-  // providers (the Default case).
-  for (auto provider : GetProvidersToRun()) {
+  for (auto provider : providers_) {
+    if (!ShouldRunProvider(provider.get()))
+      continue;
+
     provider->StartPrefetch(input);
   }
 }
@@ -1186,39 +1190,62 @@
   stop_timer_duration_ = duration;
 }
 
-AutocompleteController::Providers AutocompleteController::GetProvidersToRun() {
+bool AutocompleteController::ShouldRunProvider(AutocompleteProvider* provider) {
   if (OmniboxFieldTrial::IsSiteSearchStarterPackEnabled() &&
       input_.keyword_mode_entry_method() !=
           metrics::OmniboxEventProto_KeywordModeEntryMethod_INVALID) {
-    // We're in keyword mode. Try to grab the TemplateURL to determine which
-    // provider to run.
+    // We're in keyword mode. Only a subset of providers are run when we're in a
+    // starter pack keyword mode. Try to grab the TemplateURL to determine if
+    // we're in starter pack mode and whether this provider should be run.
     AutocompleteInput keyword_input = input_;
     const TemplateURL* keyword_turl =
         KeywordProvider::GetSubstitutingTemplateURLForInput(
             template_url_service_, &keyword_input);
-    Providers provider_subset;
     if (keyword_turl && keyword_turl->starter_pack_id() > 0) {
-      // Search provider and keyword provider are still run because we would
-      // lose the suggestion the keyword chip is attached to otherwise. Search
-      // provider suggestions are curbed for starter pack scopes in
-      // `SearchProvider::ShouldCurbDefaultSuggestions()`.
-      provider_subset.push_back(search_provider_.get());
-      provider_subset.push_back(keyword_provider_.get());
+      switch (provider->type()) {
+        // Search provider and keyword provider are still run because we would
+        // lose the suggestion the keyword chip is attached to otherwise. Search
+        // provider suggestions are curbed for starter pack scopes in
+        // `SearchProvider::ShouldCurbDefaultSuggestions()`.
+        case AutocompleteProvider::TYPE_SEARCH:
+        case AutocompleteProvider::TYPE_KEYWORD:
+          return true;
 
-      switch (keyword_turl->starter_pack_id()) {
-        case TemplateURLStarterPackData::kBookmarks:
-          provider_subset.push_back(bookmark_provider_.get());
-          break;
-        case TemplateURLStarterPackData::kHistory:
-          provider_subset.push_back(history_quick_provider_.get());
-          provider_subset.push_back(history_url_provider_.get());
-          break;
+        // @Bookmarks starter pack scope - run only the bookmarks provider.
+        case AutocompleteProvider::TYPE_BOOKMARK:
+          return (keyword_turl->starter_pack_id() ==
+                  TemplateURLStarterPackData::kBookmarks);
+
+        // @History starter pack scope - run history quick and history url
+        // providers.
+        case AutocompleteProvider::TYPE_HISTORY_QUICK:
+        case AutocompleteProvider::TYPE_HISTORY_URL:
+          return (keyword_turl->starter_pack_id() ==
+                  TemplateURLStarterPackData::kHistory);
+
+        // @Tabs starter pack scope - run the open tab provider.
+        case AutocompleteProvider::TYPE_OPEN_TAB:
+          return (keyword_turl->starter_pack_id() ==
+                  TemplateURLStarterPackData::kTabs);
+
+        // No other providers should run when in a starter pack scope.
+        default:
+          return false;
       }
-
-      return provider_subset;
     }
   }
 
+  // Open Tab Provider should only be run for @tabs starter pack mode and in the
+  // CrOS launcher.  As a temporary condition, we don't run the open tab
+  // provider when IsSiteSearchStarterPackEnabled() is true, even though that
+  // could interfere with the launcher.
+  // TODO(crbug/1287313): This needs to be updated before running live
+  // experiments.
+  if (provider->type() == AutocompleteProvider::TYPE_OPEN_TAB &&
+      OmniboxFieldTrial::IsSiteSearchStarterPackEnabled()) {
+    return false;
+  }
+
   // Otherwise, run all providers.
-  return providers_;
+  return true;
 }
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h
index 18bbee7..c5a638a 100644
--- a/components/omnibox/browser/autocomplete_controller.h
+++ b/components/omnibox/browser/autocomplete_controller.h
@@ -323,10 +323,11 @@
   // The client passed to the providers.
   std::unique_ptr<AutocompleteProviderClient> provider_client_;
 
-  // Returns a list of which providers to run based on whether we're in keyword
-  // mode and which keyword we're searching.  Currently returns all providers
-  // except when we're in keyword mode for a starter pack search engine.
-  Providers GetProvidersToRun();
+  // Returns whether the given provider should be ran based on whether we're in
+  // keyword mode and which keyword we're searching. Currently runs all enabled
+  // providers unless in a Starter Pack scope, except for OpenTabProvider which
+  // only runs on Lacros and the @tabs scope.
+  bool ShouldRunProvider(AutocompleteProvider* provider);
 
   // A list of all providers.
   Providers providers_;
diff --git a/components/omnibox/browser/omnibox_edit_model.cc b/components/omnibox/browser/omnibox_edit_model.cc
index 4c1a499..1e66c17 100644
--- a/components/omnibox/browser/omnibox_edit_model.cc
+++ b/components/omnibox/browser/omnibox_edit_model.cc
@@ -1661,6 +1661,10 @@
                      additional_text);
 }
 
+// static
+const char OmniboxEditModel::kCutOrCopyAllTextHistogram[] =
+    "Omnibox.CutOrCopyAllText";
+
 void OmniboxEditModel::SetAccessibilityLabel(const AutocompleteMatch& match) {
   view_->SetAccessibilityLabel(view_->GetText(), match, true);
 }
diff --git a/components/omnibox/browser/omnibox_edit_model.h b/components/omnibox/browser/omnibox_edit_model.h
index 0c247ebd..94e501f 100644
--- a/components/omnibox/browser/omnibox_edit_model.h
+++ b/components/omnibox/browser/omnibox_edit_model.h
@@ -412,6 +412,9 @@
   // Used for testing purposes only.
   std::u16string GetUserTextForTesting() const { return user_text_; }
 
+  // Name of the histogram tracking cut or copy omnibox commands.
+  static const char kCutOrCopyAllTextHistogram[];
+
   // Just forwards the call to the OmniboxView referred within.
   void SetAccessibilityLabel(const AutocompleteMatch& match);
 
@@ -494,6 +497,8 @@
       int* label_prefix_length = nullptr);
 
   // Invoked any time the result set of the controller changes.
+  // TODO(orinj): This method seems like a good candidate for removal; it is
+  // preserved here only to prevent possible behavior change while refactoring.
   void OnPopupResultChanged();
 
   // Lookup the bitmap for |result_index|. Returns nullptr if not found.
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.cc b/components/optimization_guide/content/browser/page_content_annotations_service.cc
index 92ae6ed..2d4350a 100644
--- a/components/optimization_guide/content/browser/page_content_annotations_service.cc
+++ b/components/optimization_guide/content/browser/page_content_annotations_service.cc
@@ -18,6 +18,7 @@
 #include "components/optimization_guide/core/noisy_metrics_recorder.h"
 #include "components/optimization_guide/core/optimization_guide_enums.h"
 #include "components/optimization_guide/core/optimization_guide_features.h"
+#include "components/optimization_guide/core/optimization_guide_logger.h"
 #include "components/optimization_guide/core/optimization_guide_model_provider.h"
 #include "components/optimization_guide/core/optimization_guide_switches.h"
 #include "content/public/browser/navigation_entry.h"
@@ -113,10 +114,12 @@
     history::HistoryService* history_service,
     leveldb_proto::ProtoDatabaseProvider* database_provider,
     const base::FilePath& database_dir,
+    OptimizationGuideLogger* optimization_guide_logger,
     scoped_refptr<base::SequencedTaskRunner> background_task_runner)
     : last_annotated_history_visits_(
           features::MaxContentAnnotationRequestsCached()),
-      annotated_text_cache_(features::MaxVisitAnnotationCacheSize()) {
+      annotated_text_cache_(features::MaxVisitAnnotationCacheSize()),
+      optimization_guide_logger_(optimization_guide_logger) {
   DCHECK(optimization_guide_model_provider);
   DCHECK(history_service);
   history_service_ = history_service;
@@ -395,10 +398,27 @@
   if (!content_annotations)
     return;
 
+  bool is_new_entry = false;
   if (annotated_text_cache_.Peek(*visit.text_to_annotate) ==
       annotated_text_cache_.end()) {
+    is_new_entry = true;
     annotated_text_cache_.Put(*visit.text_to_annotate, *content_annotations);
   }
+
+  if (is_new_entry) {
+    for (const auto& entity : content_annotations->entities) {
+      // Skip low weight entities.
+      if (entity.weight < 50)
+        continue;
+      GetMetadataForEntityId(
+          entity.id,
+          base::BindOnce(
+              &PageContentAnnotationsService::OnEntityMetadataRetrieved,
+              weak_ptr_factory_.GetWeakPtr(), visit.url, entity.id,
+              entity.weight));
+    }
+  }
+
   MaybeRecordVisibilityUKM(visit, content_annotations);
 
   if (!features::ShouldWriteContentAnnotationsToHistoryService())
@@ -557,6 +577,24 @@
            PageContentAnnotationsType::kRemoteMetdata);
 }
 
+void PageContentAnnotationsService::OnEntityMetadataRetrieved(
+    const GURL& url,
+    const std::string& entity_id,
+    int weight,
+    const absl::optional<EntityMetadata>& entity_metadata) {
+  if (!optimization_guide_logger_ || !entity_metadata.has_value())
+    return;
+
+  GURL::Replacements replacements;
+  replacements.ClearQuery();
+  replacements.ClearRef();
+
+  OPTIMIZATION_GUIDE_LOGGER(optimization_guide_logger_)
+      << "Entities: Url=" << url.ReplaceComponents(replacements)
+      << " Weight=" << std::to_string(weight) << ". "
+      << entity_metadata->ToHumanReadableString();
+}
+
 // static
 HistoryVisit PageContentAnnotationsService::CreateHistoryVisitFromWebContents(
     content::WebContents* web_contents,
diff --git a/components/optimization_guide/content/browser/page_content_annotations_service.h b/components/optimization_guide/content/browser/page_content_annotations_service.h
index e9cac58..c60f1117 100644
--- a/components/optimization_guide/content/browser/page_content_annotations_service.h
+++ b/components/optimization_guide/content/browser/page_content_annotations_service.h
@@ -34,6 +34,8 @@
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "url/gurl.h"
 
+class OptimizationGuideLogger;
+
 namespace content {
 class WebContents;
 }  // namespace content
@@ -106,6 +108,7 @@
       history::HistoryService* history_service,
       leveldb_proto::ProtoDatabaseProvider* database_provider,
       const base::FilePath& database_dir,
+      OptimizationGuideLogger* optimization_guide_logger,
       scoped_refptr<base::SequencedTaskRunner> background_task_runner);
   ~PageContentAnnotationsService() override;
   PageContentAnnotationsService(const PageContentAnnotationsService&) = delete;
@@ -236,6 +239,14 @@
       const HistoryVisit& visit,
       const proto::PageEntitiesMetadata& page_metadata);
 
+  // Called when entity metadata for |entity_id| that had weight |weight| on
+  // page with |url| has been retrieved.
+  void OnEntityMetadataRetrieved(
+      const GURL& url,
+      const std::string& entity_id,
+      int weight,
+      const absl::optional<EntityMetadata>& entity_metadata);
+
   using PersistAnnotationsCallback = base::OnceCallback<void(history::VisitID)>;
   // Queries |history_service| for all the visits to the visited URL of |visit|.
   // |callback| will be invoked to write the bound content annotations to
@@ -296,6 +307,8 @@
   // are set.
   std::unique_ptr<PageContentAnnotationsValidator> validator_;
 
+  OptimizationGuideLogger* optimization_guide_logger_ = nullptr;
+
   base::WeakPtrFactory<PageContentAnnotationsService> weak_ptr_factory_{this};
 };
 
diff --git a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc
index e53fc62b..5121fa0 100644
--- a/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc
+++ b/components/optimization_guide/content/browser/page_content_annotations_web_contents_observer_unittest.cc
@@ -47,6 +47,7 @@
                                       history_service,
                                       nullptr,
                                       base::FilePath(),
+                                      nullptr,
                                       nullptr) {}
   ~FakePageContentAnnotationsService() override = default;
 
diff --git a/components/optimization_guide/core/entity_metadata.cc b/components/optimization_guide/core/entity_metadata.cc
index 06d5d97..a8f9558 100644
--- a/components/optimization_guide/core/entity_metadata.cc
+++ b/components/optimization_guide/core/entity_metadata.cc
@@ -282,6 +282,21 @@
       base::JoinString(collections, ",").c_str());
 }
 
+std::string EntityMetadata::ToHumanReadableString() const {
+  std::vector<std::string> categories;
+  for (const auto& iter : human_readable_categories) {
+    categories.push_back(
+        base::StringPrintf("{%s,%f}", iter.first.c_str(), iter.second));
+  }
+
+  return base::StringPrintf(
+      "%s %s, %s {%s}, %s {%s}, %s {%s}",
+      "Entity:", human_readable_name.c_str(),
+      "Categories: ", base::JoinString(categories, ",").c_str(),
+      "Aliases: ", base::JoinString(human_readable_aliases, ",").c_str(),
+      "Collections: ", base::JoinString(collections, ",").c_str());
+}
+
 std::ostream& operator<<(std::ostream& out, const EntityMetadata& md) {
   out << md.ToString();
   return out;
diff --git a/components/optimization_guide/core/entity_metadata.h b/components/optimization_guide/core/entity_metadata.h
index e1bb19a..b012486 100644
--- a/components/optimization_guide/core/entity_metadata.h
+++ b/components/optimization_guide/core/entity_metadata.h
@@ -144,6 +144,8 @@
 
   std::string ToString() const;
 
+  std::string ToHumanReadableString() const;
+
   base::Value AsValue() const;
 
   friend std::ostream& operator<<(std::ostream& out, const EntityMetadata& md);
diff --git a/components/permissions/permission_uma_util.cc b/components/permissions/permission_uma_util.cc
index 1b503d02..4fd0e68 100644
--- a/components/permissions/permission_uma_util.cc
+++ b/components/permissions/permission_uma_util.cc
@@ -999,24 +999,6 @@
   base::UmaHistogramEnumeration(
       "Permissions.DSE.AutoPermissionRevertTransition." + permission_string,
       transition);
-
-  if (transition == AutoDSEPermissionRevertTransition::INVALID_END_STATE) {
-    base::UmaHistogramEnumeration(
-        "Permissions.DSE.InvalidAutoPermissionRevertTransition."
-        "BackedUpSetting." +
-            permission_string,
-        backed_up_setting, CONTENT_SETTING_NUM_SETTINGS);
-    base::UmaHistogramEnumeration(
-        "Permissions.DSE.InvalidAutoPermissionRevertTransition."
-        "EffectiveSetting." +
-            permission_string,
-        effective_setting, CONTENT_SETTING_NUM_SETTINGS);
-    base::UmaHistogramEnumeration(
-        "Permissions.DSE.InvalidAutoPermissionRevertTransition."
-        "EndStateSetting." +
-            permission_string,
-        end_state_setting, CONTENT_SETTING_NUM_SETTINGS);
-  }
 }
 
 // static
diff --git a/components/permissions/permission_uma_util_unittest.cc b/components/permissions/permission_uma_util_unittest.cc
index 2a49c7f..9668843 100644
--- a/components/permissions/permission_uma_util_unittest.cc
+++ b/components/permissions/permission_uma_util_unittest.cc
@@ -143,8 +143,6 @@
 TEST_F(PermissionUmaUtilTest, MetricsAreRecordedWhenAutoDSEPermissionReverted) {
   const std::string kTransitionHistogramPrefix =
       "Permissions.DSE.AutoPermissionRevertTransition.";
-  const std::string kInvalidTransitionHistogramPrefix =
-      "Permissions.DSE.InvalidAutoPermissionRevertTransition.";
 
   constexpr struct {
     ContentSetting backed_up_setting;
@@ -165,16 +163,6 @@
        permissions::AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_ALLOW},
       {CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_BLOCK,
        permissions::AutoDSEPermissionRevertTransition::PRESERVE_BLOCK_BLOCK},
-
-      // Invalid combinations.
-      {CONTENT_SETTING_ASK, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ASK,
-       permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
-      {CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW,
-       permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
-      {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_BLOCK,
-       permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
-      {CONTENT_SETTING_BLOCK, CONTENT_SETTING_ALLOW, CONTENT_SETTING_ALLOW,
-       permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE},
   };
 
   // We test every combination of test case for notifications and geolocation to
@@ -194,33 +182,6 @@
       histograms.ExpectBucketCount(kTransitionHistogramPrefix + type_string,
                                    test.expected_transition, 1);
       histograms.ExpectTotalCount(kTransitionHistogramPrefix + type_string, 1);
-
-      if (test.expected_transition ==
-          permissions::AutoDSEPermissionRevertTransition::INVALID_END_STATE) {
-        // If INVALID_END_STATE is recorded, there should be more histograms.
-        const std::string backed_up_histogram =
-            kInvalidTransitionHistogramPrefix + "BackedUpSetting." +
-            type_string;
-        const std::string effective_histogram =
-            kInvalidTransitionHistogramPrefix + "EffectiveSetting." +
-            type_string;
-        const std::string end_state_histogram =
-            kInvalidTransitionHistogramPrefix + "EndStateSetting." +
-            type_string;
-        histograms.ExpectBucketCount(backed_up_histogram,
-                                     test.backed_up_setting, 1);
-        histograms.ExpectBucketCount(effective_histogram,
-                                     test.effective_setting, 1);
-        histograms.ExpectBucketCount(end_state_histogram,
-                                     test.end_state_setting, 1);
-        histograms.ExpectTotalCount(backed_up_histogram, 1);
-        histograms.ExpectTotalCount(effective_histogram, 1);
-        histograms.ExpectTotalCount(end_state_histogram, 1);
-      } else {
-        EXPECT_EQ(base::HistogramTester::CountsMap(),
-                  histograms.GetTotalCountsForPrefix(
-                      "Permissions.DSE.InvalidAutoPermissionRevertTransition"));
-      }
     }
   }
 }
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn
index 7df07e1f3..46d98c5 100644
--- a/components/segmentation_platform/internal/BUILD.gn
+++ b/components/segmentation_platform/internal/BUILD.gn
@@ -85,8 +85,6 @@
     "execution/processing/sql_feature_processor.h",
     "execution/processing/uma_feature_processor.cc",
     "execution/processing/uma_feature_processor.h",
-    "input_context.cc",
-    "input_context.h",
     "local_state_helper_impl.cc",
     "local_state_helper_impl.h",
     "metadata/metadata_utils.cc",
@@ -168,8 +166,6 @@
 
   if (is_android) {
     sources += [
-      "android/segmentation_platform_conversion_bridge.cc",
-      "android/segmentation_platform_conversion_bridge.h",
       "android/segmentation_platform_service_android.cc",
       "android/segmentation_platform_service_android.h",
     ]
@@ -328,10 +324,7 @@
 if (is_android) {
   android_library("internal_java") {
     visibility = [ "//chrome/android:chrome_all_java" ]
-    sources = [
-      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java",
-      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java",
-    ]
+    sources = [ "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java" ]
 
     deps = [
       "//base:base_java",
@@ -349,9 +342,6 @@
       "//chrome/browser",
     ]
 
-    sources = [
-      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java",
-      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java",
-    ]
+    sources = [ "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformServiceImpl.java" ]
   }
 }
diff --git a/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc b/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
index 820d7ae..a5ea3b98 100644
--- a/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
+++ b/components/segmentation_platform/internal/android/segmentation_platform_service_android.cc
@@ -9,8 +9,8 @@
 #include "base/android/callback_android.h"
 #include "base/android/jni_string.h"
 #include "base/bind.h"
-#include "components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.h"
 #include "components/segmentation_platform/internal/jni_headers/SegmentationPlatformServiceImpl_jni.h"
+#include "components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h"
 #include "components/segmentation_platform/public/segment_selection_result.h"
 #include "components/segmentation_platform/public/segmentation_platform_service.h"
 #include "components/segmentation_platform/public/trigger_context.h"
diff --git a/components/segmentation_platform/internal/execution/execution_request.h b/components/segmentation_platform/internal/execution/execution_request.h
index e610475..165d003 100644
--- a/components/segmentation_platform/internal/execution/execution_request.h
+++ b/components/segmentation_platform/internal/execution/execution_request.h
@@ -9,7 +9,7 @@
 #include "base/memory/raw_ptr.h"
 #include "base/memory/scoped_refptr.h"
 #include "components/segmentation_platform/internal/execution/model_execution_status.h"
-#include "components/segmentation_platform/internal/input_context.h"
+#include "components/segmentation_platform/public/input_context.h"
 
 namespace segmentation_platform {
 namespace proto {
diff --git a/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h b/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h
index 6ade8ce5..e87654b 100644
--- a/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h
+++ b/components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h
@@ -14,8 +14,8 @@
 #include "components/segmentation_platform/internal/execution/processing/custom_input_processor.h"
 #include "components/segmentation_platform/internal/execution/processing/query_processor.h"
 #include "components/segmentation_platform/internal/execution/processing/uma_feature_processor.h"
-#include "components/segmentation_platform/internal/input_context.h"
 #include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/public/input_context.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
 
 namespace segmentation_platform {
diff --git a/components/segmentation_platform/internal/execution/processing/feature_processor_state.h b/components/segmentation_platform/internal/execution/processing/feature_processor_state.h
index befb0f4..75878ca 100644
--- a/components/segmentation_platform/internal/execution/processing/feature_processor_state.h
+++ b/components/segmentation_platform/internal/execution/processing/feature_processor_state.h
@@ -13,8 +13,8 @@
 #include "base/time/time.h"
 #include "components/segmentation_platform/internal/database/ukm_types.h"
 #include "components/segmentation_platform/internal/execution/processing/feature_list_query_processor.h"
-#include "components/segmentation_platform/internal/input_context.h"
 #include "components/segmentation_platform/internal/proto/model_metadata.pb.h"
+#include "components/segmentation_platform/public/input_context.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/components/segmentation_platform/internal/scheduler/execution_service.h b/components/segmentation_platform/internal/scheduler/execution_service.h
index 7bcf5fd..cd89f899 100644
--- a/components/segmentation_platform/internal/scheduler/execution_service.h
+++ b/components/segmentation_platform/internal/scheduler/execution_service.h
@@ -13,8 +13,8 @@
 #include "base/time/clock.h"
 #include "components/segmentation_platform/internal/execution/execution_request.h"
 #include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h"
-#include "components/segmentation_platform/internal/input_context.h"
 #include "components/segmentation_platform/internal/scheduler/model_execution_scheduler.h"
+#include "components/segmentation_platform/public/input_context.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
 
 class PrefService;
diff --git a/components/segmentation_platform/internal/selection/segment_result_provider.h b/components/segmentation_platform/internal/selection/segment_result_provider.h
index e2b931a..faebcc26 100644
--- a/components/segmentation_platform/internal/selection/segment_result_provider.h
+++ b/components/segmentation_platform/internal/selection/segment_result_provider.h
@@ -8,7 +8,7 @@
 #include "base/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "components/segmentation_platform/internal/database/segment_info_database.h"
-#include "components/segmentation_platform/internal/input_context.h"
+#include "components/segmentation_platform/public/input_context.h"
 #include "components/segmentation_platform/public/proto/segmentation_platform.pb.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h
index f40d020..897a13f4 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.h
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -9,10 +9,10 @@
 #include "base/containers/flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "components/segmentation_platform/internal/database/segment_info_database.h"
-#include "components/segmentation_platform/internal/input_context.h"
 #include "components/segmentation_platform/internal/platform_options.h"
 #include "components/segmentation_platform/internal/selection/segment_result_provider.h"
 #include "components/segmentation_platform/internal/selection/segment_selector.h"
+#include "components/segmentation_platform/public/input_context.h"
 #include "components/segmentation_platform/public/segment_selection_result.h"
 
 class PrefService;
diff --git a/components/segmentation_platform/public/BUILD.gn b/components/segmentation_platform/public/BUILD.gn
index 93d1bbb..22364f8 100644
--- a/components/segmentation_platform/public/BUILD.gn
+++ b/components/segmentation_platform/public/BUILD.gn
@@ -14,6 +14,8 @@
     "features.cc",
     "features.h",
     "field_trial_register.h",
+    "input_context.cc",
+    "input_context.h",
     "local_state_helper.h",
     "model_provider.cc",
     "model_provider.h",
@@ -39,6 +41,10 @@
   ]
 
   if (is_android) {
+    sources += [
+      "android/segmentation_platform_conversion_bridge.cc",
+      "android/segmentation_platform_conversion_bridge.h",
+    ]
     deps += [ ":jni_headers" ]
   }
 }
@@ -61,6 +67,7 @@
     sources = [
       "android/java/src/org/chromium/components/segmentation_platform/OnDemandSegmentSelectionResult.java",
       "android/java/src/org/chromium/components/segmentation_platform/SegmentSelectionResult.java",
+      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java",
       "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformService.java",
       "android/java/src/org/chromium/components/segmentation_platform/TriggerContext.java",
     ]
@@ -79,6 +86,9 @@
   generate_jni("jni_headers") {
     visibility = [ ":*" ]
 
-    sources = [ "android/java/src/org/chromium/components/segmentation_platform/TriggerContext.java" ]
+    sources = [
+      "android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java",
+      "android/java/src/org/chromium/components/segmentation_platform/TriggerContext.java",
+    ]
   }
 }
diff --git a/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java b/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java
similarity index 91%
rename from components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java
rename to components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java
index 32e304c..1ada075 100644
--- a/components/segmentation_platform/internal/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java
+++ b/components/segmentation_platform/public/android/java/src/org/chromium/components/segmentation_platform/SegmentationPlatformConversionBridge.java
@@ -9,7 +9,7 @@
 import org.chromium.components.segmentation_platform.proto.SegmentationProto.SegmentId;
 
 /**
- * Java side of the JNI bridge for various JNI conversions required by the segmentation platform.
+ * Provides JNI conversion methods for public data types provided by segmentation platform.
  */
 @JNINamespace("segmentation_platform")
 public class SegmentationPlatformConversionBridge {
diff --git a/components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.cc b/components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.cc
similarity index 85%
rename from components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.cc
rename to components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.cc
index 029aaa5..5129ccc 100644
--- a/components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.cc
+++ b/components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.cc
@@ -2,9 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.h"
+#include "components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h"
 
-#include "components/segmentation_platform/internal/jni_headers/SegmentationPlatformConversionBridge_jni.h"
+#include "components/segmentation_platform/public/jni_headers/SegmentationPlatformConversionBridge_jni.h"
 #include "components/segmentation_platform/public/segment_selection_result.h"
 #include "components/segmentation_platform/public/trigger_context.h"
 
diff --git a/components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.h b/components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h
similarity index 73%
rename from components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.h
rename to components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h
index fcc653f..4bf9e58 100644
--- a/components/segmentation_platform/internal/android/segmentation_platform_conversion_bridge.h
+++ b/components/segmentation_platform/public/android/segmentation_platform_conversion_bridge.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
-#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
 
 #include "base/android/jni_android.h"
 #include "base/memory/raw_ptr.h"
@@ -15,7 +15,7 @@
 namespace segmentation_platform {
 
 // A helper class for creating Java objects required by the segmentation
-// platform from their C++ counterparts.
+// platform public API from their C++ counterparts.
 class SegmentationPlatformConversionBridge {
  public:
   static ScopedJavaLocalRef<jobject> CreateJavaSegmentSelectionResult(
@@ -29,4 +29,4 @@
 
 }  // namespace segmentation_platform
 
-#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_ANDROID_SEGMENTATION_PLATFORM_CONVERSION_BRIDGE_H_
diff --git a/components/segmentation_platform/internal/input_context.cc b/components/segmentation_platform/public/input_context.cc
similarity index 88%
rename from components/segmentation_platform/internal/input_context.cc
rename to components/segmentation_platform/public/input_context.cc
index 203ff7e7..cfc3a64 100644
--- a/components/segmentation_platform/internal/input_context.cc
+++ b/components/segmentation_platform/public/input_context.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/segmentation_platform/internal/input_context.h"
+#include "components/segmentation_platform/public/input_context.h"
 
 #include "components/segmentation_platform/public/trigger_context.h"
 
diff --git a/components/segmentation_platform/internal/input_context.h b/components/segmentation_platform/public/input_context.h
similarity index 67%
rename from components/segmentation_platform/internal/input_context.h
rename to components/segmentation_platform/public/input_context.h
index 5ff8cfe..5146c3a 100644
--- a/components/segmentation_platform/internal/input_context.h
+++ b/components/segmentation_platform/public/input_context.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_INPUT_CONTEXT_H_
-#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_INPUT_CONTEXT_H_
+#ifndef COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_INPUT_CONTEXT_H_
+#define COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_INPUT_CONTEXT_H_
 
 #include "base/containers/flat_map.h"
 #include "base/memory/scoped_refptr.h"
@@ -13,9 +13,6 @@
 
 namespace segmentation_platform {
 
-class SegmentationTabHelper;
-
-// Experimental API, DO NOT USE.
 // Input provided for segment selection, based on the current state of the
 // browser.
 struct InputContext : base::RefCounted<InputContext> {
@@ -26,9 +23,9 @@
   InputContext(InputContext&) = delete;
   InputContext& operator=(InputContext&) = delete;
 
-  // Input values that can be used to input to model directly if the type is
-  // `Type::INTEGER` or `Type::DOUBLE`. Inputs can be substituted to SQL queries
-  // if the type is not `Type::DICT` or `Type::LIST`.
+  // A list of params that can be used as input either directly to the model, or
+  // to SQL queries, or custom input delegates. The exact mechanism and
+  // semantics is still under construction.
   base::flat_map<std::string, processing::ProcessedValue> metadata_args;
 
  private:
@@ -39,4 +36,4 @@
 
 }  // namespace segmentation_platform
 
-#endif  // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_INPUT_CONTEXT_H_
+#endif  // COMPONENTS_SEGMENTATION_PLATFORM_PUBLIC_INPUT_CONTEXT_H_
diff --git a/components/services/app_service/public/cpp/intent.cc b/components/services/app_service/public/cpp/intent.cc
index b71c81b..692560b2 100644
--- a/components/services/app_service/public/cpp/intent.cc
+++ b/components/services/app_service/public/cpp/intent.cc
@@ -214,6 +214,11 @@
   return true;
 }
 
+bool Intent::IsShareIntent() {
+  return action == apps_util::kIntentActionSend ||
+         action == apps_util::kIntentActionSendMultiple;
+}
+
 IntentFilePtr ConvertMojomIntentFileToIntentFile(
     const apps::mojom::IntentFilePtr& mojom_intent_file) {
   if (!mojom_intent_file) {
diff --git a/components/services/app_service/public/cpp/intent.h b/components/services/app_service/public/cpp/intent.h
index 39fb575..86f52f9b 100644
--- a/components/services/app_service/public/cpp/intent.h
+++ b/components/services/app_service/public/cpp/intent.h
@@ -91,6 +91,9 @@
   // Returns true if matches all existing conditions in the filter.
   bool MatchFilter(const IntentFilterPtr& filter);
 
+  // Returns true if `intent` corresponds to a share intent.
+  bool IsShareIntent();
+
   // Intent action. e.g. view, send.
   std::string action;
   // The URL of the intent. e.g. https://www.google.com/.
diff --git a/components/services/app_service/public/cpp/intent_util.h b/components/services/app_service/public/cpp/intent_util.h
index 86cad19..dde5038 100644
--- a/components/services/app_service/public/cpp/intent_util.h
+++ b/components/services/app_service/public/cpp/intent_util.h
@@ -156,6 +156,8 @@
                           const apps::mojom::IntentFilterPtr& filter);
 
 // Return true if `intent` corresponds to a share intent.
+// TODO(crbug.com/1253250): Remove this function after migrating to non-mojo
+// AppService.
 bool IsShareIntent(const apps::mojom::IntentPtr& intent);
 
 // Return true if |value| matches |pattern| with simple glob syntax.
diff --git a/components/viz/common/BUILD.gn b/components/viz/common/BUILD.gn
index 9dbc3d6..5ee0d030 100644
--- a/components/viz/common/BUILD.gn
+++ b/components/viz/common/BUILD.gn
@@ -15,9 +15,19 @@
   sources = [ "resources/resource_format.h" ]
 }
 
+# TODO(crbug.com/1330636): Remove the Fuchsia `is_chromecast` condition once
+# such builds no longer reach this file.
+always_enable_blending_for_primary =
+    is_castos || is_cast_android || (is_fuchsia && is_chromecast)
+assert(enable_cast_overlay_strategy || !always_enable_blending_for_primary)
+
 buildflag_header("buildflags") {
   header = "buildflags.h"
-  flags = [ "USE_VIZ_DEBUGGER=$use_viz_debugger" ]
+  flags = [
+    "USE_VIZ_DEBUGGER=$use_viz_debugger",
+    "ENABLE_CAST_OVERLAY_STRATEGY=$enable_cast_overlay_strategy",
+    "ALWAYS_ENABLE_BLENDING_FOR_PRIMARY=$always_enable_blending_for_primary",
+  ]
 }
 
 viz_component("resource_format_utils") {
@@ -397,6 +407,7 @@
     sources += [ "gpu/vulkan_in_process_context_provider_unittest.cc" ]
   }
   deps = [
+    ":buildflags",
     ":common",
     "//base/test:test_support",
     "//cc:test_support",
diff --git a/components/viz/common/display/overlay_strategy.cc b/components/viz/common/display/overlay_strategy.cc
index 1d647e8..f1af2591 100644
--- a/components/viz/common/display/overlay_strategy.cc
+++ b/components/viz/common/display/overlay_strategy.cc
@@ -6,6 +6,7 @@
 
 #include "base/logging.h"
 #include "base/strings/string_split.h"
+#include "components/viz/common/buildflags.h"
 
 namespace viz {
 
@@ -22,8 +23,10 @@
       strategies.push_back(OverlayStrategy::kSingleOnTop);
     } else if (strategy_name == "underlay") {
       strategies.push_back(OverlayStrategy::kUnderlay);
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
     } else if (strategy_name == "cast") {
       strategies.push_back(OverlayStrategy::kUnderlayCast);
+#endif
     } else {
       LOG(ERROR) << "Unrecognized overlay strategy " << strategy_name;
     }
diff --git a/components/viz/common/display/overlay_strategy.h b/components/viz/common/display/overlay_strategy.h
index 549b11f..9c93a1f0 100644
--- a/components/viz/common/display/overlay_strategy.h
+++ b/components/viz/common/display/overlay_strategy.h
@@ -8,6 +8,7 @@
 #include <string>
 #include <vector>
 
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/viz_common_export.h"
 
 namespace viz {
@@ -20,7 +21,9 @@
   kFullscreen = 2,
   kSingleOnTop = 3,
   kUnderlay = 4,
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
   kUnderlayCast = 5,
+#endif
   kNoStrategyAllFail = 6,
   kNoStrategyFailMin = 7,
   kMaxValue = kNoStrategyFailMin,
diff --git a/components/viz/common/display/overlay_strategy_unittest.cc b/components/viz/common/display/overlay_strategy_unittest.cc
index d0c1299..07cc456 100644
--- a/components/viz/common/display/overlay_strategy_unittest.cc
+++ b/components/viz/common/display/overlay_strategy_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <vector>
 
+#include "components/viz/common/buildflags.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -26,8 +27,12 @@
 
   EXPECT_THAT(strategies, UnorderedElementsAre(OverlayStrategy::kFullscreen,
                                                OverlayStrategy::kSingleOnTop,
-                                               OverlayStrategy::kUnderlay,
-                                               OverlayStrategy::kUnderlayCast));
+                                               OverlayStrategy::kUnderlay
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
+                                               ,
+                                               OverlayStrategy::kUnderlayCast
+#endif
+                                               ));
 }
 
 TEST(ParseOverlayStrategiesTest, BadValue) {
diff --git a/components/viz/host/gpu_host_impl.cc b/components/viz/host/gpu_host_impl.cc
index 60e908d2..199ad82 100644
--- a/components/viz/host/gpu_host_impl.cc
+++ b/components/viz/host/gpu_host_impl.cc
@@ -16,6 +16,7 @@
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
 #include "build/build_config.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/features.h"
 #include "gpu/config/gpu_driver_bug_workaround_type.h"
 #include "gpu/config/gpu_feature_info.h"
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
index a8e08ed..267af5f 100644
--- a/components/viz/service/BUILD.gn
+++ b/components/viz/service/BUILD.gn
@@ -291,12 +291,6 @@
     }
   }
 
-  # TODO(crbug.com/1330636): Remove the Fuchsia `is_chromecast` condition once
-  # such builds no longer reach this file.
-  if (is_castos || is_cast_android || (is_fuchsia && is_chromecast)) {
-    deps += [ "//chromecast/media/service/mojom" ]
-  }
-
   if (is_mac) {
     sources += [
       "display/ca_layer_overlay.cc",
@@ -327,9 +321,16 @@
       "display/overlay_strategy_single_on_top.h",
       "display/overlay_strategy_underlay.cc",
       "display/overlay_strategy_underlay.h",
+    ]
+  }
+
+  if (enable_cast_overlay_strategy) {
+    sources += [
       "display/overlay_strategy_underlay_cast.cc",
       "display/overlay_strategy_underlay_cast.h",
     ]
+
+    deps += [ "//chromecast/media/service/mojom" ]
   }
 
   if (is_android) {
@@ -360,12 +361,6 @@
     public_deps += [ "//ui/ozone" ]
   }
 
-  # TODO(crbug.com/1330636): Remove the Fuchsia `is_chromecast` condition once
-  # such builds no longer reach this file.
-  if (is_castos || is_cast_android || (is_fuchsia && is_chromecast)) {
-    defines += [ "ALWAYS_ENABLE_BLENDING_FOR_PRIMARY" ]
-  }
-
   if (is_win) {
     sources += [
       "display/dc_layer_overlay.cc",
diff --git a/components/viz/service/display/overlay_processor_delegated.cc b/components/viz/service/display/overlay_processor_delegated.cc
index b32785f..5a8a634 100644
--- a/components/viz/service/display/overlay_processor_delegated.cc
+++ b/components/viz/service/display/overlay_processor_delegated.cc
@@ -32,7 +32,6 @@
 #include "components/viz/service/display/overlay_strategy_fullscreen.h"
 #include "components/viz/service/display/overlay_strategy_single_on_top.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
-#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/components/viz/service/display/overlay_processor_interface.cc b/components/viz/service/display/overlay_processor_interface.cc
index a7f8897d..70dddf9f 100644
--- a/components/viz/service/display/overlay_processor_interface.cc
+++ b/components/viz/service/display/overlay_processor_interface.cc
@@ -11,6 +11,7 @@
 #include "build/build_config.h"
 #include "build/chromecast_buildflags.h"
 #include "build/chromeos_buildflags.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/display/renderer_settings.h"
 #include "components/viz/common/features.h"
 #include "components/viz/service/display/display_compositor_memory_and_task_controller.h"
@@ -202,7 +203,7 @@
   overlay_plane.display_rect =
       gfx::RectF(viewport_size.width(), viewport_size.height());
 
-#if defined(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
+#if BUILDFLAG(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
   // On Chromecast, always use RGBA as the scanout format for the primary plane.
   overlay_plane.enable_blending = true;
 #endif
diff --git a/components/viz/service/display/overlay_processor_ozone.cc b/components/viz/service/display/overlay_processor_ozone.cc
index 1266269..9ca6976 100644
--- a/components/viz/service/display/overlay_processor_ozone.cc
+++ b/components/viz/service/display/overlay_processor_ozone.cc
@@ -15,16 +15,20 @@
 #include "base/timer/elapsed_timer.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/features.h"
 #include "components/viz/service/display/overlay_strategy_fullscreen.h"
 #include "components/viz/service/display/overlay_strategy_single_on_top.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
-#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
 #include "gpu/command_buffer/service/shared_image_manager.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
+#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
+#endif
+
 namespace viz {
 
 namespace {
@@ -151,10 +155,12 @@
       case OverlayStrategy::kUnderlay:
         strategies_.push_back(std::make_unique<OverlayStrategyUnderlay>(this));
         break;
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
       case OverlayStrategy::kUnderlayCast:
         strategies_.push_back(
             std::make_unique<OverlayStrategyUnderlayCast>(this));
         break;
+#endif
       default:
         NOTREACHED();
     }
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.cc b/components/viz/service/display/overlay_strategy_underlay_cast.cc
index a30825bb..3f68454 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.cc
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.cc
@@ -9,23 +9,20 @@
 
 #include "base/containers/adapters.h"
 #include "base/logging.h"
+#include "base/no_destructor.h"
 #include "base/unguessable_token.h"
 #include "build/chromecast_buildflags.h"
 #include "components/viz/common/quads/draw_quad.h"
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/common/quads/video_hole_draw_quad.h"
 #include "components/viz/service/display/overlay_candidate_factory.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
-#include "base/no_destructor.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#endif
-
 namespace viz {
+
 namespace {
 
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
 // This persistent mojo::Remote is bound then used by all the instances
 // of OverlayStrategyUnderlayCast.
 mojo::Remote<chromecast::media::mojom::VideoGeometrySetter>&
@@ -35,7 +32,6 @@
       g_video_geometry_setter;
   return *g_video_geometry_setter;
 }
-#endif
 
 }  // namespace
 
@@ -265,14 +261,12 @@
 void OverlayStrategyUnderlayCast::CommitCandidate(
     const OverlayProposedCandidate& proposed_candidate,
     AggregatedRenderPass* render_pass) {
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
   DCHECK(GetVideoGeometrySetter());
   GetVideoGeometrySetter()->SetVideoGeometry(
       proposed_candidate.candidate.display_rect,
       proposed_candidate.candidate.transform,
       VideoHoleDrawQuad::MaterialCast(*proposed_candidate.quad_iter)
           ->overlay_plane_id);
-#endif
 
   if (proposed_candidate.candidate.has_mask_filter) {
     render_pass->ReplaceExistingQuadWithSolidColor(
@@ -288,13 +282,11 @@
   return OverlayStrategy::kUnderlayCast;
 }
 
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
 // static
 void OverlayStrategyUnderlayCast::ConnectVideoGeometrySetter(
     mojo::PendingRemote<chromecast::media::mojom::VideoGeometrySetter>
         video_geometry_setter) {
   GetVideoGeometrySetter().Bind(std::move(video_geometry_setter));
 }
-#endif
 
 }  // namespace viz
diff --git a/components/viz/service/display/overlay_strategy_underlay_cast.h b/components/viz/service/display/overlay_strategy_underlay_cast.h
index 8dbafc5..f455e2c 100644
--- a/components/viz/service/display/overlay_strategy_underlay_cast.h
+++ b/components/viz/service/display/overlay_strategy_underlay_cast.h
@@ -8,14 +8,11 @@
 #include <memory>
 #include <vector>
 
-#include "build/chromecast_buildflags.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
 #include "components/viz/service/viz_service_export.h"
 
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
 #include "chromecast/media/service/mojom/video_geometry_setter.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#endif
 
 namespace viz {
 // Similar to underlay strategy plus Cast-specific handling of content bounds.
@@ -66,7 +63,6 @@
   void CommitCandidate(const OverlayProposedCandidate& proposed_candidate,
                        AggregatedRenderPass* render_pass) override;
 
-#if BUILDFLAG(IS_CASTOS) || BUILDFLAG(IS_CAST_ANDROID)
   // In Chromecast build, OverlayStrategyUnderlayCast needs a valid mojo
   // interface to VideoGeometrySetter Service (shared by all instances of
   // OverlaystrategyUnderlayCast). This must be called before compositor starts.
@@ -75,7 +71,6 @@
   static void ConnectVideoGeometrySetter(
       mojo::PendingRemote<chromecast::media::mojom::VideoGeometrySetter>
           video_geometry_setter);
-#endif
 
   OverlayStrategy GetUMAEnum() const override;
 
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index b6621a0..0d4016d 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -21,6 +21,7 @@
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/resource_provider_test_utils.h"
 #include "components/viz/client/client_resource_provider.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/quads/aggregated_render_pass_draw_quad.h"
 #include "components/viz/common/quads/compositor_render_pass.h"
@@ -44,7 +45,6 @@
 #include "components/viz/service/display/overlay_strategy_fullscreen.h"
 #include "components/viz/service/display/overlay_strategy_single_on_top.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
-#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
 #include "components/viz/test/fake_skia_output_surface.h"
 #include "components/viz/test/test_context_provider.h"
 #include "components/viz/test/test_gles2_interface.h"
@@ -63,6 +63,10 @@
 #include "ui/base/ui_base_features.h"
 #endif
 
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
+#include "components/viz/service/display/overlay_strategy_underlay_cast.h"
+#endif
+
 using testing::_;
 using testing::Mock;
 
@@ -361,12 +365,14 @@
   }
 };
 
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
 class UnderlayCastOverlayProcessor : public DefaultOverlayProcessor {
  public:
   UnderlayCastOverlayProcessor() : DefaultOverlayProcessor() {
     strategies_.push_back(std::make_unique<OverlayStrategyUnderlayCast>(this));
   }
 };
+#endif
 
 class ChangeThresholdOnTopOverlayProcessor : public DefaultOverlayProcessor {
  public:
@@ -406,20 +412,6 @@
   return pass;
 }
 
-std::unique_ptr<AggregatedRenderPass> CreateRenderPassWithTransform(
-    const gfx::Transform& transform) {
-  AggregatedRenderPassId render_pass_id{1};
-  gfx::Rect output_rect(0, 0, 256, 256);
-
-  auto pass = std::make_unique<AggregatedRenderPass>();
-  pass->SetNew(render_pass_id, output_rect, output_rect, gfx::Transform());
-
-  SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
-  shared_state->opacity = 1.f;
-  shared_state->quad_to_target_transform = transform;
-  return pass;
-}
-
 static ResourceId CreateResourceInLayerTree(
     ClientResourceProvider* child_resource_provider,
     const gfx::Size& size,
@@ -551,6 +543,21 @@
       RGBA_8888, test_surface_id);
 }
 
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
+std::unique_ptr<AggregatedRenderPass> CreateRenderPassWithTransform(
+    const gfx::Transform& transform) {
+  AggregatedRenderPassId render_pass_id{1};
+  gfx::Rect output_rect(0, 0, 256, 256);
+
+  auto pass = std::make_unique<AggregatedRenderPass>();
+  pass->SetNew(render_pass_id, output_rect, output_rect, gfx::Transform());
+
+  SharedQuadState* shared_state = pass->CreateAndAppendSharedQuadState();
+  shared_state->opacity = 1.f;
+  shared_state->quad_to_target_transform = transform;
+  return pass;
+}
+
 // For Cast we use VideoHoleDrawQuad, and that's what overlay_processor_
 // expects.
 VideoHoleDrawQuad* CreateVideoHoleDrawQuadAt(
@@ -563,6 +570,7 @@
   overlay_quad->SetNew(shared_quad_state, rect, rect, overlay_plane_id);
   return overlay_quad;
 }
+#endif
 
 TextureDrawQuad* CreateTransparentCandidateQuadAt(
     DisplayResourceProvider* parent_resource_provider,
@@ -768,7 +776,9 @@
 using UnderlayTest = OverlayTest<UnderlayOverlayProcessor>;
 using TransparentUnderlayTest =
     OverlayTest<TransparentUnderlayOverlayProcessor>;
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
 using UnderlayCastTest = OverlayTest<UnderlayCastOverlayProcessor>;
+#endif
 using MultiOverlayTest = UseMultipleOverlaysTest<MultiOverlayProcessor>;
 using MultiUnderlayTest = UseMultipleOverlaysTest<MultiUnderlayProcessor>;
 using SizeSortedMultiOverlayTest =
@@ -3676,7 +3686,9 @@
     }
   }
 }
+#endif  // !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_WIN)
 
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
 TEST_F(UnderlayCastTest, ReplacementQuad) {
   auto pass = CreateRenderPass();
   CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
@@ -3965,9 +3977,9 @@
       SkBlendMode::kDstOut,
       pass_list.front()->quad_list.front()->shared_quad_state->blend_mode);
 }
-#endif
+#endif  // BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
 
-#if defined(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
+#if BUILDFLAG(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
 TEST_F(UnderlayCastTest, PrimaryPlaneOverlayIsAlwaysTransparent) {
   auto pass = CreateRenderPass();
   gfx::Rect output_rect = pass->output_rect;
@@ -3982,9 +3994,10 @@
   AggregatedRenderPassList pass_list;
   pass_list.push_back(std::move(pass));
   auto output_surface_plane = overlay_processor_->ProcessOutputSurfaceAsOverlay(
-      kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace(),
+      kDisplaySize, kDisplaySize, kDefaultBufferFormat, gfx::ColorSpace(),
       false /* has_alpha */, 1.0f /* opacity */, gpu::Mailbox());
 
+  SurfaceDamageRectList surface_damage_rect_list;
   overlay_processor_->ProcessForOverlays(
       resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
       render_pass_filters, render_pass_backdrop_filters,
@@ -3994,7 +4007,7 @@
   ASSERT_EQ(true, output_surface_plane.enable_blending);
   EXPECT_EQ(0U, content_bounds_.size());
 }
-#endif
+#endif  // BUILDFLAG(ALWAYS_ENABLE_BLENDING_FOR_PRIMARY)
 
 #if BUILDFLAG(IS_APPLE)
 class CALayerOverlayRPDQTest : public CALayerOverlayTest {
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index 8275099..1887b23 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -17,6 +17,7 @@
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/memory_dump_manager.h"
 #include "build/build_config.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/features.h"
 #include "components/viz/service/debugger/viz_debugger.h"
 #include "components/viz/service/performance_hint/hint_session.h"
diff --git a/components/viz/viz.gni b/components/viz/viz.gni
index b7d27ef..c1d8c0a 100644
--- a/components/viz/viz.gni
+++ b/components/viz/viz.gni
@@ -19,6 +19,11 @@
 
 enable_dawn_backend_tests = skia_use_dawn && enable_skia_dawn_gtests
 
+# TODO(crbug.com/1330636): Remove the Fuchsia `is_chromecast` condition once
+# such builds no longer reach this file.
+enable_cast_overlay_strategy =
+    is_castos || is_cast_android || (is_fuchsia && is_chromecast)
+
 viz_remove_configs = []
 viz_add_configs = [ "//build/config:precompiled_headers" ]
 
diff --git a/content/browser/content_index/content_index_service_impl.cc b/content/browser/content_index/content_index_service_impl.cc
index 9df1efe3..00f7808 100644
--- a/content/browser/content_index/content_index_service_impl.cc
+++ b/content/browser/content_index/content_index_service_impl.cc
@@ -47,6 +47,13 @@
 
   RenderProcessHost* render_process_host = render_frame_host->GetProcess();
   DCHECK(render_process_host);
+
+  if (render_frame_host->IsNestedWithinFencedFrame()) {
+    mojo::ReportBadMessage(
+        "Content Index API is not allowed in a fenced frame");
+    return;
+  }
+
   auto* storage_partition = static_cast<StoragePartitionImpl*>(
       render_process_host->GetStoragePartition());
 
@@ -74,6 +81,16 @@
   auto* storage_partition = static_cast<StoragePartitionImpl*>(
       render_process_host->GetStoragePartition());
 
+  scoped_refptr<ServiceWorkerRegistration> registration =
+      storage_partition->GetServiceWorkerContext()->GetLiveRegistration(
+          info.registration_id);
+  if (registration && registration->ancestor_frame_type() ==
+                          blink::mojom::AncestorFrameType::kFencedFrame) {
+    mojo::ReportBadMessage(
+        "Content Index API is not allowed in a fenced frame");
+    return;
+  }
+
   mojo::MakeSelfOwnedReceiver(std::make_unique<ContentIndexServiceImpl>(
                                   info.storage_key.origin(),
                                   storage_partition->GetContentIndexContext(),
diff --git a/content/browser/devtools/protocol/input_handler.cc b/content/browser/devtools/protocol/input_handler.cc
index fd26c9c..fa1c5a20 100644
--- a/content/browser/devtools/protocol/input_handler.cc
+++ b/content/browser/devtools/protocol/input_handler.cc
@@ -717,16 +717,15 @@
       widget_host = target_host;
   }
 
-  // If replacement start and end are not specified, then they are -1,
+  // If replacement start and end are not specified, then the range is invalid,
   // so no replacing will be done.
-  int replacement_start_out = -1;
-  int replacement_end_out = -1;
+  gfx::Range replacement_range = gfx::Range::InvalidRange();
 
   // Check if replacement_start and end parameters were passed in
   if (replacement_start.isJust()) {
-    replacement_start_out = replacement_start.fromJust();
+    replacement_range.set_start(replacement_start.fromJust());
     if (replacement_end.isJust()) {
-      replacement_end_out = replacement_end.fromJust();
+      replacement_range.set_end(replacement_end.fromJust());
     } else {
       callback->sendFailure(Response::InvalidParams(
           "Either both replacement start/end are specified or neither."));
@@ -740,9 +739,8 @@
   widget_host->Focus();
 
   widget_host->GetWidgetInputHandler()->ImeSetComposition(
-      text16, std::vector<ui::ImeTextSpan>(),
-      gfx::Range(replacement_start_out, replacement_end_out), selection_start,
-      selection_end, std::move(closure));
+      text16, std::vector<ui::ImeTextSpan>(), replacement_range,
+      selection_start, selection_end, std::move(closure));
 }
 
 void InputHandler::DispatchMouseEvent(
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.cc b/content/browser/renderer_host/back_forward_cache_metrics.cc
index a84ff35c..f9ef0059 100644
--- a/content/browser/renderer_host/back_forward_cache_metrics.cc
+++ b/content/browser/renderer_host/back_forward_cache_metrics.cc
@@ -182,10 +182,6 @@
       SCOPED_CRASH_KEY_NUMBER(
           "BFCacheMismatch", "disallow_activation",
           page_store_result_->disallow_activation_reasons().size());
-      SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "navigation_type",
-                              navigation->navigation_type());
-      SCOPED_CRASH_KEY_BOOL("BFCacheMismatch", "did_replace",
-                            navigation->DidReplaceEntry());
       SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "restore_type",
                               static_cast<int>(navigation->GetRestoreType()));
       SCOPED_CRASH_KEY_STRING256("BFCacheMismatch", "url",
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index 382b56b..1513d6d6 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -1477,6 +1477,7 @@
   NavigationEntryImpl* active_entry = GetLastCommittedEntry();
   active_entry->SetTimestamp(timestamp);
   active_entry->SetHttpStatusCode(params.http_status_code);
+
   // TODO(altimin, crbug.com/933147): Remove this logic after we are done with
   // implementing back-forward cache.
   if (back_forward_cache_metrics &&
@@ -1488,6 +1489,13 @@
   // `back_forward_cache_metrics()` may return null as we do not record
   // back-forward cache metrics for navigations in non-primary frame trees.
   if (active_entry->back_forward_cache_metrics()) {
+    // TODO(https://crbug.com/1338089): Remove this.
+    // These are both only available from details at this point, so we capture
+    // them here.
+    SCOPED_CRASH_KEY_NUMBER("BFCacheMismatch", "navigation_type",
+                            details->type);
+    SCOPED_CRASH_KEY_BOOL("BFCacheMismatch", "did_replace",
+                          details->did_replace_entry);
     active_entry->back_forward_cache_metrics()->DidCommitNavigation(
         navigation_request,
         back_forward_cache_.IsAllowed(navigation_request->GetURL()));
diff --git a/content/public/common/result_codes.h b/content/public/common/result_codes.h
index 00ff24c..e5ab17f 100644
--- a/content/public/common/result_codes.h
+++ b/content/public/common/result_codes.h
@@ -46,6 +46,9 @@
   RESULT_CODE_LAST_CODE
 };
 
+static_assert(RESULT_CODE_KILLED_BAD_MESSAGE == 3,
+              "This enum is frozen - process_posix.cc may spy on this value.");
+
 static_assert(RESULT_CODE_LAST_CODE == 5,
               "This enum is frozen - see the IMPORTANT note above.");
 
diff --git a/content/renderer/media/media_factory.cc b/content/renderer/media/media_factory.cc
index f209783..c62bcf8 100644
--- a/content/renderer/media/media_factory.cc
+++ b/content/renderer/media/media_factory.cc
@@ -439,10 +439,12 @@
       render_frame_->GetTaskRunner(blink::TaskType::kInternalMedia),
       std::move(handlers));
 
+  EnsureDecoderFactory();
+
   base::WeakPtr<media::MediaObserver> media_observer;
   auto factory_selector = CreateRendererFactorySelector(
       media_log.get(), url, render_frame_->GetRenderFrameMediaPlaybackOptions(),
-      GetDecoderFactory().get(),
+      decoder_factory_.get(),
       std::make_unique<blink::RemotePlaybackClientWrapperImpl>(client),
       &media_observer);
 
@@ -801,6 +803,11 @@
 }
 
 base::WeakPtr<media::DecoderFactory> MediaFactory::GetDecoderFactory() {
+  EnsureDecoderFactory();
+  return decoder_factory_->GetWeakPtr();
+}
+
+void MediaFactory::EnsureDecoderFactory() {
   if (!decoder_factory_) {
     std::unique_ptr<media::DecoderFactory> external_decoder_factory;
 #if BUILDFLAG(ENABLE_MOJO_AUDIO_DECODER) || BUILDFLAG(ENABLE_MOJO_VIDEO_DECODER)
@@ -815,8 +822,6 @@
     decoder_factory_ = std::make_unique<media::DefaultDecoderFactory>(
         std::move(external_decoder_factory));
   }
-
-  return decoder_factory_->GetWeakPtr();
 }
 
 #if BUILDFLAG(ENABLE_MEDIA_REMOTING)
diff --git a/content/renderer/media/media_factory.h b/content/renderer/media/media_factory.h
index 599ecec..1ea98609 100644
--- a/content/renderer/media/media_factory.h
+++ b/content/renderer/media/media_factory.h
@@ -112,9 +112,13 @@
   blink::WebEncryptedMediaClient* EncryptedMediaClient();
 
   // Returns `DecoderFactory`, which can be used to created decoders in WebRTC.
+  // Can be dereferenced only on the media thread.
   base::WeakPtr<media::DecoderFactory> GetDecoderFactory();
 
  private:
+  // Initializes `decoder_factory_` if it hasn't been initialized yet.
+  void EnsureDecoderFactory();
+
   std::unique_ptr<media::RendererFactorySelector> CreateRendererFactorySelector(
       media::MediaLog* media_log,
       blink::WebURL url,
diff --git a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
index e01fee0..3cf8b9bf 100644
--- a/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/maps_expectations.txt
@@ -77,6 +77,9 @@
 ###################
 # Non-"Skip" expectations go here to suppress regular flakes/failures.
 
+# Flakes on Linux Release (AMD RX 5500 XT)
+crbug.com/1340081 [ linux release amd-0x7340 ] Maps_maps [ Failure ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index 7dad90a..c04a479 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -413,8 +413,12 @@
 # Vulkan Swiftshader WebGPU interop - missing source image
 crbug.com/1307787 [ linux skia-renderer-vulkan ] Pixel_VulkanSwiftShader_WebGPUImportVideoFrameUnacceleratedOffscreenCanvas [ Failure ]
 
+# Flakes on Android
 crbug.com/1203317 [ android android-shield-android-tv no-passthrough ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
 crbug.com/1203317 [ android android-pixel-2 no-passthrough ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
+crbug.com/1203317 [ android android-pixel-6 no-passthrough android-chromium ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
+
+crbug.com/1287249 [ android android-pixel-6 passthrough skia-renderer-vulkan android-chromium ] Pixel_Video_MP4_FourColors_Rot_180 [ Failure ]
 
 # Flakes on Mac Release (Intel)
 crbug.com/982292 [ mac release intel-0x3e9b ] Pixel_BackgroundImage [ RetryOnFailure ]
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn
index a8ca7a5..01563a9 100644
--- a/extensions/browser/BUILD.gn
+++ b/extensions/browser/BUILD.gn
@@ -459,6 +459,8 @@
     "notification_types.h",
     "null_app_sorting.cc",
     "null_app_sorting.h",
+    "offscreen_document_host.cc",
+    "offscreen_document_host.h",
     "path_util.cc",
     "path_util.h",
     "permissions_manager.cc",
diff --git a/extensions/browser/computed_hashes.cc b/extensions/browser/computed_hashes.cc
index 84d21e7e..a782b5b4 100644
--- a/extensions/browser/computed_hashes.cc
+++ b/extensions/browser/computed_hashes.cc
@@ -256,12 +256,12 @@
     int block_size = hash_info.block_size;
     const std::vector<std::string>& hashes = hash_info.hashes;
 
-    base::Value::ListStorage block_hashes;
+    base::Value::List block_hashes;
     block_hashes.reserve(hashes.size());
     for (const auto& hash : hashes) {
       std::string encoded;
       base::Base64Encode(hash, &encoded);
-      block_hashes.push_back(base::Value(std::move(encoded)));
+      block_hashes.Append(std::move(encoded));
     }
 
     base::Value dict(base::Value::Type::DICTIONARY);
diff --git a/extensions/browser/extension_host.cc b/extensions/browser/extension_host.cc
index 70279e6b..4c6c778 100644
--- a/extensions/browser/extension_host.cc
+++ b/extensions/browser/extension_host.cc
@@ -56,6 +56,7 @@
       initial_url_(url),
       extension_host_type_(host_type) {
   DCHECK(host_type == mojom::ViewType::kExtensionBackgroundPage ||
+         host_type == mojom::ViewType::kOffscreenDocument ||
          host_type == mojom::ViewType::kExtensionDialog ||
          host_type == mojom::ViewType::kExtensionPopup);
   host_contents_ = WebContents::Create(
diff --git a/extensions/browser/offscreen_document_host.cc b/extensions/browser/offscreen_document_host.cc
new file mode 100644
index 0000000..e31238c
--- /dev/null
+++ b/extensions/browser/offscreen_document_host.cc
@@ -0,0 +1,40 @@
+// 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 "extensions/browser/offscreen_document_host.h"
+
+#include "base/check.h"
+#include "base/feature_list.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_features.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace extensions {
+
+OffscreenDocumentHost::OffscreenDocumentHost(
+    const Extension& extension,
+    content::SiteInstance* site_instance,
+    const GURL& url)
+    : ExtensionHost(&extension,
+                    site_instance,
+                    url,
+                    mojom::ViewType::kOffscreenDocument) {
+  DCHECK(base::FeatureList::IsEnabled(
+      extensions_features::kExtensionsOffscreenDocuments));
+  DCHECK_EQ(url::Origin::Create(url), extension.origin());
+  DCHECK_GE(extension.manifest_version(), 3);
+}
+
+OffscreenDocumentHost::~OffscreenDocumentHost() = default;
+
+void OffscreenDocumentHost::OnDidStopFirstLoad() {
+  // Nothing to do for offscreen documents.
+}
+
+bool OffscreenDocumentHost::IsBackgroundPage() const {
+  return false;
+}
+
+}  // namespace extensions
diff --git a/extensions/browser/offscreen_document_host.h b/extensions/browser/offscreen_document_host.h
new file mode 100644
index 0000000..448e609
--- /dev/null
+++ b/extensions/browser/offscreen_document_host.h
@@ -0,0 +1,42 @@
+// 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 EXTENSIONS_BROWSER_OFFSCREEN_DOCUMENT_HOST_H_
+#define EXTENSIONS_BROWSER_OFFSCREEN_DOCUMENT_HOST_H_
+
+#include "extensions/browser/extension_host.h"
+
+class GURL;
+
+namespace content {
+class SiteInstance;
+}
+
+namespace extensions {
+class Extension;
+
+// A host for offscreen extension documents. These are essentially WebContents
+// owned by an extension that are rendered offscreen. Unlike background pages,
+// these cannot register "lazy" event listeners; they will not be respawned
+// in response to API events.
+class OffscreenDocumentHost : public ExtensionHost {
+ public:
+  OffscreenDocumentHost(const Extension& extension,
+                        content::SiteInstance* site_instance,
+                        const GURL& url);
+
+  OffscreenDocumentHost(const OffscreenDocumentHost&) = delete;
+  OffscreenDocumentHost& operator=(const OffscreenDocumentHost&) = delete;
+
+  ~OffscreenDocumentHost() override;
+
+ private:
+  // ExtensionHost:
+  void OnDidStopFirstLoad() override;
+  bool IsBackgroundPage() const override;
+};
+
+}  // namespace extensions
+
+#endif  // EXTENSIONS_BROWSER_OFFSCREEN_DOCUMENT_HOST_H_
diff --git a/extensions/browser/permissions_manager.cc b/extensions/browser/permissions_manager.cc
index cf22b0a..47809ed9 100644
--- a/extensions/browser/permissions_manager.cc
+++ b/extensions/browser/permissions_manager.cc
@@ -18,6 +18,7 @@
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_process_host.h"
 #include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_registry_factory.h"
 #include "extensions/browser/extension_util.h"
 #include "extensions/browser/extensions_browser_client.h"
@@ -26,6 +27,7 @@
 #include "extensions/browser/pref_types.h"
 #include "extensions/browser/renderer_startup_helper.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/manifest_handlers/permissions_parser.h"
 #include "extensions/common/mojom/renderer.mojom.h"
 #include "extensions/common/permissions/permission_set.h"
 #include "extensions/common/permissions/permissions_data.h"
@@ -205,9 +207,76 @@
 
   user_permissions_.permitted_sites.insert(origin);
   AddSiteToPrefs(extension_prefs_, kPermittedSites, origin);
+
   OnUserPermissionsSettingsChanged();
 }
 
+void PermissionsManager::UpdatePermissionsWithUserSettings(
+    const Extension& extension,
+    const PermissionSet& user_permitted_set) {
+  // If either user cannot withhold permissions from the extension (as is the
+  // case for e.g. policy-installed extensions) or the user has not withheld
+  // any permissions for the extension, then we don't need to do anything - the
+  // extension already has all its requested permissions.
+  if (!util::CanWithholdPermissionsFromExtension(extension) ||
+      !HasWithheldHostPermissions(extension.id())) {
+    return;
+  }
+
+  // TODO(https://crbug.com/1268198): Much of this logic is similar to the
+  // logic from PermissionsUpdater::InitializePermissions(). We should have the
+  // PermissionsUpdater use this (or replace it with this, though there's
+  // some complications there).
+
+  // Otherwise, calculate out the new set of permissions for the extension.
+  // This calculation is:
+  // 1) Take the set of all allowed permissions. This is the union of
+  //    runtime-granted permissions (where the user said "this extension may run
+  //    on this site") and `user_permitted_set` (sites the user allows any
+  //    extension to run on).
+  std::unique_ptr<const PermissionSet> allowed_permissions =
+      PermissionSet::CreateUnion(user_permitted_set,
+                                 *GetRuntimePermissionsFromPrefs(extension));
+
+  // 2) Calculate the set of all permissions the extension requests. This is the
+  //    union of optional and required permissions in the extension's manifest.
+  const PermissionSet& required_permissions =
+      PermissionsParser::GetRequiredPermissions(&extension);
+  std::unique_ptr<const PermissionSet> requested_permissions =
+      PermissionSet::CreateUnion(
+          required_permissions,
+          PermissionsParser::GetOptionalPermissions(&extension));
+
+  // 3) Determine the active permissions, within the bounds of requested
+  //    permissions. "Active permissions" here are the permissions the extension
+  //    most recently set for itself, as extensions can revoke their own
+  //    permissions via chrome.permissions.remove() (which removes the
+  //    permission from the active set, but not the granted set).
+  std::unique_ptr<const PermissionSet> stored_active_permissions =
+      extension_prefs_->GetActivePermissions(extension.id());
+  std::unique_ptr<const PermissionSet> bounded_active =
+      PermissionSet::CreateIntersection(*stored_active_permissions,
+                                        *requested_permissions);
+
+  // 4) Calculate the new active and withheld permissions. The active
+  //    permissions are the intersection of all permissions the extension is
+  //    allowed to have with all permissions the extension elected to have.
+  //    Said differently, we grant a permission if both the extension and the
+  //    user approved it.
+  //    Withheld permissions are any required permissions that are not in the
+  //    new active set.
+  std::unique_ptr<const PermissionSet> new_active =
+      PermissionSet::CreateIntersection(
+          *allowed_permissions, *bounded_active,
+          URLPatternSet::IntersectionBehavior::kDetailed);
+  std::unique_ptr<const PermissionSet> new_withheld =
+      PermissionSet::CreateDifference(required_permissions, *new_active);
+
+  // Set the new permissions on the extension.
+  extension.permissions_data()->SetPermissions(std::move(new_active),
+                                               std::move(new_withheld));
+}
+
 void PermissionsManager::RemoveUserPermittedSite(const url::Origin& origin) {
   if (RemovePermittedSiteAndUpdatePrefs(origin))
     OnUserPermissionsSettingsChanged();
@@ -374,7 +443,7 @@
   observers_.RemoveObserver(observer);
 }
 
-void PermissionsManager::OnUserPermissionsSettingsChanged() const {
+void PermissionsManager::OnUserPermissionsSettingsChanged() {
   // TODO(http://crbug.com/1268198): AddOrigin() below can fail if the
   // added URLPattern doesn't parse (such as if the schemes are invalid). We
   // need to make sure that origins added to this list only contain schemes that
@@ -386,7 +455,24 @@
   for (const auto& site : user_permissions_.permitted_sites)
     user_allowed_sites.AddOrigin(Extension::kValidHostPermissionSchemes, site);
 
-  // Send the new policy to the renderers.
+  PermissionSet user_allowed_set(APIPermissionSet(), ManifestPermissionSet(),
+                                 user_allowed_sites.Clone(),
+                                 user_allowed_sites.Clone());
+
+  // Update all installed extensions with the new user permissions. We do this
+  // for all installed extensions (and not just enabled extensions) so that
+  // entries in the chrome://extensions page for disabled extensions are
+  // accurate.
+  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
+  auto all_extensions = registry->GenerateInstalledExtensionsSet();
+  for (const auto& extension : *all_extensions) {
+    UpdatePermissionsWithUserSettings(*extension, user_allowed_set);
+  }
+
+  // Send the new permissions states to the renderers, including both the
+  // updated user host settings and the updated permissions for each extension.
+  // Unlike above, we only care about enabled extensions here, since disabled
+  // extensions aren't running.
   {
     ExtensionsBrowserClient* browser_client = ExtensionsBrowserClient::Get();
     for (content::RenderProcessHost::iterator host_iterator(
@@ -403,6 +489,17 @@
         if (renderer) {
           renderer->UpdateUserHostRestrictions(user_blocked_sites.Clone(),
                                                user_allowed_sites.Clone());
+          for (const auto& extension : registry->enabled_extensions()) {
+            const PermissionsData* permissions_data =
+                extension->permissions_data();
+            renderer->UpdatePermissions(
+                extension->id(),
+                std::move(*permissions_data->active_permissions().Clone()),
+                std::move(*permissions_data->withheld_permissions().Clone()),
+                permissions_data->policy_blocked_hosts(),
+                permissions_data->policy_allowed_hosts(),
+                permissions_data->UsesDefaultPolicyHostRestrictions());
+          }
         }
       }
     }
diff --git a/extensions/browser/permissions_manager.h b/extensions/browser/permissions_manager.h
index a6e8f22..e9626a7 100644
--- a/extensions/browser/permissions_manager.h
+++ b/extensions/browser/permissions_manager.h
@@ -154,7 +154,7 @@
 
  private:
   // Called whenever `user_permissions_` have changed.
-  void OnUserPermissionsSettingsChanged() const;
+  void OnUserPermissionsSettingsChanged();
 
   // Removes `origin` from the list of sites the user has allowed all
   // extensions to run on and saves the change to `extension_prefs_`. Returns if
@@ -166,6 +166,14 @@
   // Returns if the site has been removed.
   bool RemoveRestrictedSiteAndUpdatePrefs(const url::Origin& origin);
 
+  // Updates the given `extension` with the new `user_permitted_set` of sites
+  // all extensions are allowed to run on. Note that this only updates the
+  // permissions in the browser; updates must then be sent separately to the
+  // renderer and network service.
+  void UpdatePermissionsWithUserSettings(
+      const Extension& extension,
+      const PermissionSet& user_permitted_set);
+
   // Notifies observers of a permissions change.
   void NotifyObserversOfChange();
 
diff --git a/extensions/browser/process_manager.cc b/extensions/browser/process_manager.cc
index 1952407..9637cfe41 100644
--- a/extensions/browser/process_manager.cc
+++ b/extensions/browser/process_manager.cc
@@ -191,6 +191,7 @@
 
       case extensions::mojom::ViewType::kInvalid:
       case extensions::mojom::ViewType::kExtensionBackgroundPage:
+      case extensions::mojom::ViewType::kOffscreenDocument:
         return false;
     }
     NOTREACHED();
diff --git a/extensions/browser/process_map.cc b/extensions/browser/process_map.cc
index ce4eb21..d91b97d 100644
--- a/extensions/browser/process_map.cc
+++ b/extensions/browser/process_map.cc
@@ -146,6 +146,18 @@
     return Feature::BLESSED_WEB_PAGE_CONTEXT;
   }
 
+  // TODO(https://crbug.com/1339382): Currently, offscreen document contexts
+  // are misclassified as BLESSED_EXTENSION_CONTEXTs. This is not ideal
+  // because there is a mismatch between the browser and the renderer), but it's
+  // not a security issue because, while offscreen documents have fewer
+  // capabilities, this is an API distinction, and not a security enforcement.
+  // Offscreen documents run in the same process as the rest of the extension
+  // and can message the extension, so could easily - though indirectly -
+  // access all the same features.
+  // Even so, we should fix this to properly classify offscreen documents (and
+  // this would be a problem if offscreen documents ever have access to APIs
+  // that BLESSED_EXTENSION_CONTEXTs don't).
+
   return is_lock_screen_context_ ? Feature::LOCK_SCREEN_EXTENSION_CONTEXT
                                  : Feature::BLESSED_EXTENSION_CONTEXT;
 }
diff --git a/extensions/browser/service_worker_task_queue.cc b/extensions/browser/service_worker_task_queue.cc
index 583b04f..0493106 100644
--- a/extensions/browser/service_worker_task_queue.cc
+++ b/extensions/browser/service_worker_task_queue.cc
@@ -161,6 +161,23 @@
     return;
   }
 
+  // HACK: The service worker layer might invoke this callback with an ID for a
+  // RenderProcessHost that has already terminated. This isn't the right fix for
+  // this, because it results in the internal state here stalling out - we'll
+  // wait on the browser side to be ready, which will never happen. This should
+  // be cleaned up on the next activation sequence, but this still isn't good.
+  // The proper fix here is that the service worker layer shouldn't be invoking
+  // this callback with stale processes.
+  // https://crbug.com/1335821.
+  if (!content::RenderProcessHost::FromID(process_id)) {
+    // NOTE: The following is an antipattern [1]. We have this as a temporary
+    // hack to avoid crashing for stable users while the bug is addressed.
+    // [1]
+    // https://chromium.googlesource.com/chromium/src/+/HEAD/styleguide/c++/c++-dos-and-donts.md#guarding-with-dcheck_is_on
+    NOTREACHED();
+    return;
+  }
+
   UMA_HISTOGRAM_BOOLEAN("Extensions.ServiceWorkerBackground.StartWorkerStatus",
                         true);
   UMA_HISTOGRAM_TIMES("Extensions.ServiceWorkerBackground.StartWorkerTime",
diff --git a/extensions/common/api/_api_features.json b/extensions/common/api/_api_features.json
index 654a400..adc0f52 100644
--- a/extensions/common/api/_api_features.json
+++ b/extensions/common/api/_api_features.json
@@ -479,6 +479,7 @@
       "content_script",
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "web_page"
     ],
@@ -499,6 +500,7 @@
     "contexts": [
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "content_script"
     ]
@@ -507,6 +509,7 @@
     "contexts": [
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "content_script"
     ]
@@ -520,6 +523,7 @@
     "contexts": [
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "content_script"
     ]
@@ -532,6 +536,7 @@
     "contexts": [
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "content_script"
     ]
@@ -543,6 +548,7 @@
       "content_script",
       "blessed_extension",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension",
       "web_page"
     ],
@@ -631,6 +637,7 @@
       "blessed_web_page",
       "content_script",
       "lock_screen_extension",
+      "offscreen_extension",
       "unblessed_extension"
     ]
   }, {
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc
index 766ba87..52790fd 100644
--- a/extensions/common/extension_features.cc
+++ b/extensions/common/extension_features.cc
@@ -102,4 +102,8 @@
     "AvoidEarlyExtensionScriptContextCreation",
     base::FEATURE_ENABLED_BY_DEFAULT};
 
+// The feature enabling offscreen documents in Manifest V3 extensions.
+const base::Feature kExtensionsOffscreenDocuments{
+    "ExtensionsOffscreenDocuments", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace extensions_features
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h
index 3083c76..37c56d6 100644
--- a/extensions/common/extension_features.h
+++ b/extensions/common/extension_features.h
@@ -39,6 +39,8 @@
 
 extern const base::Feature kAvoidEarlyExtensionScriptContextCreation;
 
+extern const base::Feature kExtensionsOffscreenDocuments;
+
 }  // namespace extensions_features
 
 #endif  // EXTENSIONS_COMMON_EXTENSION_FEATURES_H_
diff --git a/extensions/common/features/feature.h b/extensions/common/features/feature.h
index 58023a3..f0d7a66b 100644
--- a/extensions/common/features/feature.h
+++ b/extensions/common/features/feature.h
@@ -42,6 +42,7 @@
     WEBUI_CONTEXT,
     WEBUI_UNTRUSTED_CONTEXT,
     LOCK_SCREEN_EXTENSION_CONTEXT,
+    OFFSCREEN_EXTENSION_CONTEXT,
   };
 
   // The platforms the feature is supported in.
diff --git a/extensions/common/features/simple_feature.cc b/extensions/common/features/simple_feature.cc
index f34cb5c..5355233a 100644
--- a/extensions/common/features/simple_feature.cc
+++ b/extensions/common/features/simple_feature.cc
@@ -131,6 +131,8 @@
       return "webui untrusted";
     case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
       return "lock screen app";
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
+      return "offscreen document";
   }
   NOTREACHED();
   return "";
diff --git a/extensions/common/mojom/view_type.mojom b/extensions/common/mojom/view_type.mojom
index 3691a50..03af9fa 100644
--- a/extensions/common/mojom/view_type.mojom
+++ b/extensions/common/mojom/view_type.mojom
@@ -31,4 +31,6 @@
   // DEPRECATED_kPanel = 8,
 
   kTabContents = 9,
-};
\ No newline at end of file
+
+  kOffscreenDocument = 10,
+};
diff --git a/extensions/renderer/api_activity_logger.cc b/extensions/renderer/api_activity_logger.cc
index da55e93..6e21ffa0a 100644
--- a/extensions/renderer/api_activity_logger.cc
+++ b/extensions/renderer/api_activity_logger.cc
@@ -85,7 +85,7 @@
   converter->SetFunctionAllowed(true);
   converter->SetStrategy(&strategy);
 
-  base::Value::ListStorage value_args;
+  base::Value::List value_args;
   value_args.reserve(arguments.size());
   // TODO(devlin): This doesn't protect against custom properties, so it might
   // not perfectly reflect the passed arguments.
@@ -94,20 +94,19 @@
         converter->FromV8Value(arg, context);
     if (!converted_arg)
       converted_arg = std::make_unique<base::Value>();
-    value_args.push_back(
+    value_args.Append(
         base::Value::FromUniquePtrValue(std::move(converted_arg)));
   }
 
   LogInternal(ipc_sender, IPCMessageSender::ActivityLogCallType::APICALL,
               script_context->GetExtensionID(), call_name,
-              std::make_unique<base::ListValue>(std::move(value_args)),
-              std::string());
+              std::move(value_args), std::string());
 }
 
 void APIActivityLogger::LogEvent(IPCMessageSender* ipc_sender,
                                  ScriptContext* script_context,
                                  const std::string& event_name,
-                                 std::unique_ptr<base::ListValue> arguments) {
+                                 base::Value::List arguments) {
   if (!IsLoggingEnabled())
     return;
 
@@ -144,7 +143,7 @@
   }
 
   // Get the array of call arguments.
-  base::Value::ListStorage arguments;
+  base::Value::List arguments;
   v8::Local<v8::Array> arg_array = v8::Local<v8::Array>::Cast(args[2]);
   if (arg_array->Length() > 0) {
     arguments.reserve(arg_array->Length());
@@ -160,13 +159,13 @@
           arg_array->Get(context, i).ToLocalChecked(), context);
       if (!converted_arg)
         converted_arg = std::make_unique<base::Value>();
-      arguments.push_back(
+      arguments.Append(
           base::Value::FromUniquePtrValue(std::move(converted_arg)));
     }
   }
 
   LogInternal(ipc_sender_, call_type, extension_id, call_name,
-              std::make_unique<base::ListValue>(std::move(arguments)), extra);
+              std::move(arguments), extra);
 }
 
 // static
@@ -175,12 +174,14 @@
     const IPCMessageSender::ActivityLogCallType call_type,
     const std::string& extension_id,
     const std::string& call_name,
-    std::unique_ptr<base::ListValue> arguments,
+    base::Value::List arguments,
     const std::string& extra) {
   DCHECK(IsLoggingEnabled());
   ExtensionHostMsg_APIActionOrEvent_Params params;
   params.api_call = call_name;
-  params.arguments.Swap(arguments.get());
+  // TODO(https://crbug.com/1187062): Switch to base::Value::List instead of
+  // base::ListValue, which is deprecated.
+  params.arguments.GetList() = std::move(arguments);
   params.extra = extra;
   ipc_sender->SendActivityLogIPC(extension_id, call_type, params);
 }
diff --git a/extensions/renderer/api_activity_logger.h b/extensions/renderer/api_activity_logger.h
index fb4c5e6..2ea8dbd 100644
--- a/extensions/renderer/api_activity_logger.h
+++ b/extensions/renderer/api_activity_logger.h
@@ -9,14 +9,11 @@
 #include <string>
 #include <vector>
 
+#include "base/values.h"
 #include "extensions/renderer/ipc_message_sender.h"
 #include "extensions/renderer/object_backed_native_handler.h"
 #include "v8/include/v8-forward.h"
 
-namespace base {
-class ListValue;
-}
-
 namespace extensions {
 
 // Used to log extension API calls and events that are implemented with custom
@@ -49,7 +46,7 @@
   static void LogEvent(IPCMessageSender* ipc_sender,
                        ScriptContext* script_context,
                        const std::string& event_name,
-                       std::unique_ptr<base::ListValue> arguments);
+                       base::Value::List arguments);
 
   static void set_log_for_testing(bool log);
 
@@ -68,7 +65,7 @@
                           const IPCMessageSender::ActivityLogCallType call_type,
                           const std::string& extension_id,
                           const std::string& call_name,
-                          std::unique_ptr<base::ListValue> arguments,
+                          base::Value::List arguments,
                           const std::string& extra);
 
   // Not owned by |this|.
diff --git a/extensions/renderer/bindings/api_signature.cc b/extensions/renderer/bindings/api_signature.cc
index 9a0d69e..b69948f 100644
--- a/extensions/renderer/bindings/api_signature.cc
+++ b/extensions/renderer/bindings/api_signature.cc
@@ -636,7 +636,7 @@
     }
   }
 
-  base::Value::ListStorage json;
+  base::Value::List json;
   json.reserve(size);
 
   std::unique_ptr<content::V8ValueConverter> converter =
@@ -656,10 +656,10 @@
       // null). Duplicate that behavior here.
       converted = std::make_unique<base::Value>();
     }
-    json.push_back(base::Value::FromUniquePtrValue(std::move(converted)));
+    json.Append(base::Value::FromUniquePtrValue(std::move(converted)));
   }
 
-  result.arguments_list = std::make_unique<base::ListValue>(std::move(json));
+  result.arguments_list = std::make_unique<base::Value>(std::move(json));
   return result;
 }
 
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc
index fa06a47..604a5e1f3 100644
--- a/extensions/renderer/dispatcher.cc
+++ b/extensions/renderer/dispatcher.cc
@@ -441,6 +441,11 @@
       UMA_HISTOGRAM_TIMES(
           "Extensions.DidCreateScriptContext_LockScreenExtension", elapsed);
       break;
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
+      // We don't really care about offscreen extension context initialization
+      // time at the moment - it's a strict subset (and very similar to)
+      // blessed extension context time.
+      break;
   }
 
   VLOG(1) << "Num tracked contexts: " << script_context_set_->size();
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 3c304dfa..d2ffd83d 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -526,6 +526,7 @@
       break;
     case Feature::BLESSED_EXTENSION_CONTEXT:
     case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
     case Feature::UNBLESSED_EXTENSION_CONTEXT:
     case Feature::CONTENT_SCRIPT_CONTEXT:
     case Feature::WEBUI_CONTEXT:
diff --git a/extensions/renderer/native_renderer_messaging_service.cc b/extensions/renderer/native_renderer_messaging_service.cc
index 69119cffd..1ca9356 100644
--- a/extensions/renderer/native_renderer_messaging_service.cc
+++ b/extensions/renderer/native_renderer_messaging_service.cc
@@ -492,23 +492,22 @@
 
   if (binding::IsContextValid(v8_context) &&
       APIActivityLogger::IsLoggingEnabled()) {
-    std::vector<base::Value> list;
+    base::Value::List list;
     list.reserve(2u);
     if (info.source_endpoint.extension_id)
-      list.emplace_back(*info.source_endpoint.extension_id);
+      list.Append(*info.source_endpoint.extension_id);
     else if (info.source_endpoint.native_app_name)
-      list.emplace_back(*info.source_endpoint.native_app_name);
+      list.Append(*info.source_endpoint.native_app_name);
     else
-      list.emplace_back();
+      list.Append(base::Value());
 
     if (!info.source_url.is_empty())
-      list.emplace_back(info.source_url.spec());
+      list.Append(info.source_url.spec());
     else
-      list.emplace_back();
+      list.Append(base::Value());
 
-    APIActivityLogger::LogEvent(
-        bindings_system_->GetIPCMessageSender(), script_context, event_name,
-        std::make_unique<base::ListValue>(std::move(list)));
+    APIActivityLogger::LogEvent(bindings_system_->GetIPCMessageSender(),
+                                script_context, event_name, std::move(list));
   }
 }
 
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc
index 2418f3c9..8f86fc15 100644
--- a/extensions/renderer/script_context.cc
+++ b/extensions/renderer/script_context.cc
@@ -137,6 +137,8 @@
       return "WEBUI_UNTRUSTED";
     case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
       return "LOCK_SCREEN_EXTENSION";
+    case Feature::OFFSCREEN_EXTENSION_CONTEXT:
+      return "OFFSCREEN_EXTENSION_CONTEXT";
   }
   NOTREACHED();
   return std::string();
diff --git a/extensions/renderer/script_context_set.cc b/extensions/renderer/script_context_set.cc
index 1cd3ed8..02c46e9 100644
--- a/extensions/renderer/script_context_set.cc
+++ b/extensions/renderer/script_context_set.cc
@@ -5,12 +5,15 @@
 #include "extensions/renderer/script_context_set.h"
 
 #include "base/bind.h"
+#include "base/feature_list.h"
 #include "base/location.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/public/common/url_constants.h"
 #include "content/public/renderer/render_frame.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_features.h"
+#include "extensions/renderer/extension_frame_helper.h"
 #include "extensions/renderer/extensions_renderer_client.h"
 #include "extensions/renderer/script_context.h"
 #include "extensions/renderer/script_injection.h"
@@ -46,13 +49,30 @@
   const Extension* effective_extension =
       GetExtensionFromFrameAndWorld(frame, world_id, true);
 
+  mojom::ViewType view_type = mojom::ViewType::kInvalid;
+  content::RenderFrame* render_frame =
+      content::RenderFrame::FromWebFrame(frame);
+  // In production, we should always have a corresponding render frame.
+  // Unfortunately, this isn't the case in unit tests, so we can't DCHECK here.
+  if (render_frame) {
+    ExtensionFrameHelper* frame_helper =
+        ExtensionFrameHelper::Get(render_frame);
+    DCHECK(frame_helper);
+    view_type = frame_helper->view_type();
+    // We should only find an offscreen document if the corresponding feature
+    // is enabled.
+    DCHECK(base::FeatureList::IsEnabled(
+               extensions_features::kExtensionsOffscreenDocuments) ||
+           view_type != mojom::ViewType::kOffscreenDocument);
+  }
   GURL frame_url = ScriptContext::GetDocumentLoaderURLForFrame(frame);
   Feature::Context context_type = ClassifyJavaScriptContext(
-      extension, world_id, frame_url, frame->GetDocument().GetSecurityOrigin());
+      extension, world_id, frame_url, frame->GetDocument().GetSecurityOrigin(),
+      view_type);
   Feature::Context effective_context_type = ClassifyJavaScriptContext(
       effective_extension, world_id,
       ScriptContext::GetEffectiveDocumentURLForContext(frame, frame_url, true),
-      frame->GetDocument().GetSecurityOrigin());
+      frame->GetDocument().GetSecurityOrigin(), view_type);
 
   ScriptContext* context =
       new ScriptContext(v8_context, frame, extension, context_type,
@@ -179,7 +199,8 @@
     const Extension* extension,
     int32_t world_id,
     const GURL& url,
-    const blink::WebSecurityOrigin& origin) {
+    const blink::WebSecurityOrigin& origin,
+    mojom::ViewType view_type) {
   // WARNING: This logic must match ProcessMap::GetContextType, as much as
   // possible.
 
@@ -215,10 +236,17 @@
       return Feature::BLESSED_WEB_PAGE_CONTEXT;
     }
 
-    return is_lock_screen_context_ ? Feature::LOCK_SCREEN_EXTENSION_CONTEXT
-                                   : Feature::BLESSED_EXTENSION_CONTEXT;
+    if (is_lock_screen_context_)
+      return Feature::LOCK_SCREEN_EXTENSION_CONTEXT;
+    if (view_type == mojom::ViewType::kOffscreenDocument)
+      return Feature::OFFSCREEN_EXTENSION_CONTEXT;
+    return Feature::BLESSED_EXTENSION_CONTEXT;
   }
 
+  // None of the following feature types should ever be present in an
+  // offscreen document.
+  DCHECK_NE(mojom::ViewType::kOffscreenDocument, view_type);
+
   // TODO(kalman): This IsOpaque() check is wrong, it should be performed as
   // part of ScriptContext::IsSandboxedPage().
   if (!origin.IsOpaque() &&
diff --git a/extensions/renderer/script_context_set.h b/extensions/renderer/script_context_set.h
index c8d4ab7d..e8fce41 100644
--- a/extensions/renderer/script_context_set.h
+++ b/extensions/renderer/script_context_set.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "extensions/common/extension_id.h"
 #include "extensions/common/features/feature.h"
+#include "extensions/common/mojom/view_type.mojom.h"
 #include "extensions/renderer/renderer_extension_registry.h"
 #include "extensions/renderer/script_context_set_iterable.h"
 #include "url/gurl.h"
@@ -122,7 +123,8 @@
       const Extension* extension,
       int32_t world_id,
       const GURL& url,
-      const blink::WebSecurityOrigin& origin);
+      const blink::WebSecurityOrigin& origin,
+      mojom::ViewType view_type);
 
   // Weak reference to all installed Extensions that are also active in this
   // process.
diff --git a/gpu/command_buffer/service/shared_image_backing_ozone.cc b/gpu/command_buffer/service/shared_image_backing_ozone.cc
index c634715..80a4d52 100644
--- a/gpu/command_buffer/service/shared_image_backing_ozone.cc
+++ b/gpu/command_buffer/service/shared_image_backing_ozone.cc
@@ -141,6 +141,8 @@
                      context_state_.get(), format(), size(), alpha_type())) {
       DLOG(ERROR) << "Failed to write pixels.";
     }
+  } else if (in_fence) {
+    external_write_fence_ = in_fence->GetGpuFenceHandle().Clone();
   }
 }
 
@@ -421,12 +423,25 @@
     read_fences_.clear();
   }
 
-  // If current stream is different than last_write_stream_ then wait on that
-  // stream's write_fence_ (except on ARM Mali boards for ChromeOS).
+  // Always wait on an `external_write_fence_` if present.
+  if (!external_write_fence_.is_null()) {
+    DCHECK(write_fence_.is_null());  // `write_fence_` should be null.
+    // For write access we expect new `write_fence_` so we can move the
+    // old fence here.
+    if (!readonly)
+      fences->emplace_back(std::move(external_write_fence_));
+    else
+      fences->emplace_back(external_write_fence_.Clone());
+  }
+
+  // If current stream is different than `last_write_stream_` then wait on that
+  // stream's `write_fence_` (except on ARM Mali boards for ChromeOS).
   if (!write_fence_.is_null() && (workarounds_.add_fence_for_same_gl_context ||
                                   last_write_stream_ != access_stream)) {
-    // For write access we expect new write_fence_ so we can move the old fence
-    // here.
+    DCHECK(external_write_fence_
+               .is_null());  // `external_write_fence_` should be null.
+    // For write access we expect new `write_fence_` so we can move the old
+    // fence here.
     if (!readonly)
       fences->emplace_back(std::move(write_fence_));
     else
diff --git a/gpu/command_buffer/service/shared_image_backing_ozone.h b/gpu/command_buffer/service/shared_image_backing_ozone.h
index bdbcc8f..e5926cc3 100644
--- a/gpu/command_buffer/service/shared_image_backing_ozone.h
+++ b/gpu/command_buffer/service/shared_image_backing_ozone.h
@@ -125,6 +125,8 @@
 
   scoped_refptr<gfx::NativePixmap> pixmap_;
   scoped_refptr<base::RefCountedData<DawnProcTable>> dawn_procs_;
+  // Write fence that is external and does not do Begin/EndAccess (eg. exo)
+  gfx::GpuFenceHandle external_write_fence_;
   gfx::GpuFenceHandle write_fence_;
   base::flat_map<AccessStream, gfx::GpuFenceHandle> read_fences_;
   AccessStream last_write_stream_;
diff --git a/ios/chrome/browser/snapshots/snapshot_cache.mm b/ios/chrome/browser/snapshots/snapshot_cache.mm
index c4b3bd18..295738e 100644
--- a/ios/chrome/browser/snapshots/snapshot_cache.mm
+++ b/ios/chrome/browser/snapshots/snapshot_cache.mm
@@ -17,6 +17,7 @@
 #include "base/files/file_util.h"
 #import "base/ios/crb_protocol_observers.h"
 #include "base/logging.h"
+#import "base/mac/backup_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/path_service.h"
 #include "base/sequence_checker.h"
@@ -195,8 +196,10 @@
       return;
   }
   UIImage* grey_image = GreyImage(color_image);
-  WriteImageToDisk(grey_image, ImagePath(snapshot_id, IMAGE_TYPE_GREYSCALE,
-                                         image_scale, cache_directory));
+  base::FilePath image_path = ImagePath(snapshot_id, IMAGE_TYPE_GREYSCALE,
+                                        image_scale, cache_directory);
+  WriteImageToDisk(grey_image, image_path);
+  base::mac::SetBackupExclusion(image_path);
 }
 
 void MigrateSnapshotsWithIDs(const base::FilePath& old_cache_directory,
diff --git a/ios/chrome/browser/ui/settings/privacy/BUILD.gn b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
index 771c821..e756f1e 100644
--- a/ios/chrome/browser/ui/settings/privacy/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/privacy/BUILD.gn
@@ -146,6 +146,7 @@
     "//ios/chrome/browser/ui/table_view:utils",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/test:test_support",
+    "//ios/components/security_interstitials/https_only_mode:feature",
     "//ios/web/public/test",
     "//testing/gtest",
     "//third_party/ocmock:ocmock",
diff --git a/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm
index f7cb5c52..349c906d 100644
--- a/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/privacy/privacy_table_view_controller_unittest.mm
@@ -32,6 +32,7 @@
 #include "ios/chrome/grit/ios_chromium_strings.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
+#import "ios/components/security_interstitials/https_only_mode/feature.h"
 #include "ios/web/public/test/web_task_environment.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -63,6 +64,8 @@
   PrivacyTableViewControllerTestConfigEnhancedProtectionEnabled = 1 << 0,
   // Tests should run with Third-party intents in Incognito flag enabled.
   PrivacyTableViewControllerTestConfig3PIntentsInIncognitoEnabled = 1 << 1,
+  // Tests should run with HTTPS-Only Mode flag enabled.
+  PrivacyTableViewControllerTestConfigHttpsOnlyModeSettingEnabled = 1 << 2,
 };
 
 // `ScopedFeatureList` wrapper so `PrivacyTableViewControllerTest` can ensure
@@ -110,6 +113,15 @@
       enabledDisabledFeatures.second.push_back(kIOS3PIntentsInIncognito);
     }
 
+    if (GetParam() &
+        PrivacyTableViewControllerTestConfigHttpsOnlyModeSettingEnabled) {
+      enabledDisabledFeatures.first.push_back(
+          security_interstitials::features::kHttpsOnlyMode);
+    } else {
+      enabledDisabledFeatures.second.push_back(
+          security_interstitials::features::kHttpsOnlyMode);
+    }
+
     return enabledDisabledFeatures;
   }
 
diff --git a/ios/components/security_interstitials/https_only_mode/feature.cc b/ios/components/security_interstitials/https_only_mode/feature.cc
index 79f261d..93b03fdb6 100644
--- a/ios/components/security_interstitials/https_only_mode/feature.cc
+++ b/ios/components/security_interstitials/https_only_mode/feature.cc
@@ -8,7 +8,7 @@
 namespace features {
 
 const base::Feature kHttpsOnlyMode{"HttpsOnlyMode",
-                                   base::FEATURE_DISABLED_BY_DEFAULT};
+                                   base::FEATURE_ENABLED_BY_DEFAULT};
 
 }  // namespace features
 }  // namespace security_interstitials
diff --git a/ios/components/security_interstitials/https_only_mode/feature.h b/ios/components/security_interstitials/https_only_mode/feature.h
index 8ba9d64c..2d17ddff 100644
--- a/ios/components/security_interstitials/https_only_mode/feature.h
+++ b/ios/components/security_interstitials/https_only_mode/feature.h
@@ -10,7 +10,8 @@
 namespace security_interstitials {
 namespace features {
 
-// Enables HTTPS-Only mode upgrades on iOS.
+// Enables the HTTPS-Only mode UI setting on iOS. The user has to enable
+// the UI setting under "Privacy and Security" to use HTTPS-Only Mode.
 extern const base::Feature kHttpsOnlyMode;
 
 }  // namespace features
diff --git a/net/dns/dns_transaction.cc b/net/dns/dns_transaction.cc
index b41ce26..e9a71412 100644
--- a/net/dns/dns_transaction.cc
+++ b/net/dns/dns_transaction.cc
@@ -1530,7 +1530,6 @@
             result = StartQuery();
           }
           break;
-        case ERR_CONNECTION_REFUSED:
         case ERR_DNS_TIMED_OUT:
           timer_.Stop();
 
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index 4d1f64ba..20fd16a 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -3996,6 +3996,115 @@
   helper0.RunUntilComplete();
 }
 
+// Test that ERR_CONNECTION_REFUSED error after fallback of DnsTCPAttempt
+// should not cause DCHECK failure (https://crbug.com/1334250).
+TEST_F(DnsTransactionTestWithMockTime, TcpConnectionRefusedAfterFallback) {
+  ConfigureNumServers(2);
+  ConfigureFactory();
+  socket_factory_->diverse_source_ports_ = false;
+
+  // Data for UDP attempts to set `low_entropy` flag.
+  for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
+    AddQueryAndResponse(0 /* id */, kT0HostName, kT0Qtype, kT0ResponseDatagram,
+                        std::size(kT0ResponseDatagram), ASYNC, Transport::UDP);
+  }
+
+  // Data for TCP attempt.
+  std::unique_ptr<DnsSocketData> data1(new DnsSocketData(
+      0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::TCP));
+  data1->AddReadError(ERR_IO_PENDING, ASYNC);
+  data1->AddReadError(ERR_CONNECTION_REFUSED, ASYNC);
+  SequencedSocketData* sequenced_socket_data1 = data1->GetProvider();
+  AddSocketData(std::move(data1));
+
+  std::unique_ptr<DnsSocketData> data2(new DnsSocketData(
+      0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::TCP));
+  data2->AddReadError(ERR_IO_PENDING, ASYNC);
+  data2->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
+                         ASYNC);
+  SequencedSocketData* sequenced_socket_data2 = data2->GetProvider();
+  AddSocketData(std::move(data2));
+
+  // DNS transactions for UDP attempts to set `low_entropy` flag.
+  for (int i = 0; i <= DnsUdpTracker::kPortReuseThreshold; ++i) {
+    TransactionHelper udp_helper(kT0RecordCount);
+    udp_helper.StartTransaction(transaction_factory_.get(), kT0HostName,
+                                kT0Qtype, false /* secure */,
+                                resolve_context_.get());
+    udp_helper.RunUntilComplete();
+  }
+
+  ASSERT_TRUE(session_->udp_tracker()->low_entropy());
+
+  // DNS transactions for TCP attempt.
+  TransactionHelper helper0(kT0RecordCount);
+  helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
+                           false /* secure */, resolve_context_.get());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(helper0.has_completed());
+
+  base::TimeDelta timeout = resolve_context_->NextClassicFallbackPeriod(
+      0 /* classic_server_index */, 0 /* attempt */, session_.get());
+  FastForwardBy(timeout);
+
+  // Resume the first query.
+  sequenced_socket_data1->Resume();
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(helper0.has_completed());
+
+  // Resume the second query.
+  sequenced_socket_data2->Resume();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(helper0.has_completed());
+}
+
+// Test that ERR_CONNECTION_REFUSED error after fallback of DnsHTTPAttempt
+// should not cause DCHECK failure (https://crbug.com/1334250).
+TEST_F(DnsTransactionTestWithMockTime, HttpsConnectionRefusedAfterFallback) {
+  ConfigureDohServers(false /* use_post */, 2 /* num_doh_servers */,
+                      true /* make_available */);
+
+  std::unique_ptr<DnsSocketData> data1(new DnsSocketData(
+      0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
+      nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128));
+  data1->AddReadError(ERR_IO_PENDING, ASYNC);
+  data1->AddReadError(ERR_CONNECTION_REFUSED, ASYNC);
+  SequencedSocketData* sequenced_socket_data1 = data1->GetProvider();
+  AddSocketData(std::move(data1), false /* enqueue_transaction_id */);
+
+  std::unique_ptr<DnsSocketData> data2(new DnsSocketData(
+      0 /* id */, kT0HostName, kT0Qtype, ASYNC, Transport::HTTPS,
+      nullptr /* opt_rdata */, DnsQuery::PaddingStrategy::BLOCK_LENGTH_128));
+  data2->AddReadError(ERR_IO_PENDING, ASYNC);
+  data2->AddResponseData(kT0ResponseDatagram, std::size(kT0ResponseDatagram),
+                         ASYNC);
+  SequencedSocketData* sequenced_socket_data2 = data2->GetProvider();
+  AddSocketData(std::move(data2), false /* enqueue_transaction_id */);
+
+  TransactionHelper helper0(kT0RecordCount);
+  helper0.StartTransaction(transaction_factory_.get(), kT0HostName, kT0Qtype,
+                           true /* secure */, resolve_context_.get());
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(helper0.has_completed());
+
+  base::TimeDelta timeout = resolve_context_->NextDohFallbackPeriod(
+      0 /* doh_server_index */, session_.get());
+  FastForwardBy(timeout);
+
+  // Resume the first query.
+  sequenced_socket_data1->Resume();
+
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(helper0.has_completed());
+
+  // Resume the second query.
+  sequenced_socket_data2->Resume();
+
+  EXPECT_TRUE(helper0.has_completed());
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 14fa8ada..33147f0 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -363,8 +363,8 @@
       request_info.load_flags |= ~LOAD_DO_NOT_SAVE_COOKIES;
   }
 
-  std::string key =
-      GenerateCacheKey(&request_info, /*use_single_keyed_cache=*/false);
+  std::string key = GenerateCacheKeyForRequest(
+      &request_info, /*use_single_keyed_cache=*/false);
   disk_cache_->OnExternalCacheHit(key);
 }
 
@@ -462,8 +462,8 @@
 
   // TODO(https://crbug.com/1325315): Support looking in the single-keyed cache
   // for the resource.
-  std::string key =
-      GenerateCacheKey(&request_info, /*use_single_keyed_cache=*/false);
+  std::string key = GenerateCacheKeyForRequest(
+      &request_info, /*use_single_keyed_cache=*/false);
   disk_cache::EntryResult entry_result = disk_cache_->OpenEntry(
       key, net::IDLE,
       base::BindOnce(&HttpCache::ResourceExistenceCheckCallback, GetWeakPtr(),
@@ -476,8 +476,73 @@
 }
 
 // static
-std::string HttpCache::GenerateCacheKeyForTest(const HttpRequestInfo* request) {
-  return GenerateCacheKey(request, /*use_single_keyed_cache=*/false);
+// Generate a key that can be used inside the cache.
+std::string HttpCache::GenerateCacheKey(
+    const GURL& url,
+    int load_flags,
+    const NetworkIsolationKey& network_isolation_key,
+    int64_t upload_data_identifier,
+    bool is_subframe_document_resource,
+    bool use_single_keyed_cache,
+    const std::string& single_key_checksum) {
+  // The first character of the key may vary depending on whether or not sending
+  // credentials is permitted for this request. This only happens if the
+  // SplitCacheByIncludeCredentials feature is enabled, or if the single-keyed
+  // cache is enabled. The single-keyed cache must always be split by
+  // credentials in order to make coep:credentialless work safely.
+  const char credential_key =
+      ((base::FeatureList::IsEnabled(
+            features::kSplitCacheByIncludeCredentials) ||
+        use_single_keyed_cache) &&
+       (load_flags & LOAD_DO_NOT_SAVE_COOKIES))
+          ? '0'
+          : '1';
+
+  std::string isolation_key;
+  if (use_single_keyed_cache) {
+    DCHECK(IsSplitCacheEnabled());
+    DCHECK(!(load_flags &
+             (net::LOAD_VALIDATE_CACHE | net::LOAD_BYPASS_CACHE |
+              net::LOAD_SKIP_CACHE_VALIDATION | net::LOAD_ONLY_FROM_CACHE |
+              net::LOAD_DISABLE_CACHE | net::LOAD_SKIP_VARY_CHECK)));
+    isolation_key = base::StrCat(
+        {kSingleKeyPrefix, single_key_checksum, kSingleKeySeparator});
+  } else if (IsSplitCacheEnabled()) {
+    // Prepend the key with |kDoubleKeyPrefix| = "_dk_" to mark it as
+    // double-keyed (and makes it an invalid url so that it doesn't get
+    // confused with a single-keyed entry). Separate the origin and url
+    // with invalid whitespace character |kDoubleKeySeparator|.
+    DCHECK(network_isolation_key.IsFullyPopulated());
+    std::string subframe_document_resource_prefix =
+        is_subframe_document_resource ? kSubframeDocumentResourcePrefix : "";
+    isolation_key =
+        base::StrCat({kDoubleKeyPrefix, subframe_document_resource_prefix,
+                      network_isolation_key.ToString(), kDoubleKeySeparator});
+  }
+
+  // The key format is:
+  // credential_key/upload_data_identifier/[isolation_key]url
+
+  // Strip out the reference, username, and password sections of the URL and
+  // concatenate with the credential_key, the post_key, and the network
+  // isolation key if we are splitting the cache.
+  return base::StringPrintf("%c/%" PRId64 "/%s%s", credential_key,
+                            upload_data_identifier, isolation_key.c_str(),
+                            HttpUtil::SpecForRequest(url).c_str());
+}
+
+// static
+std::string HttpCache::GenerateCacheKeyForRequest(
+    const HttpRequestInfo* request,
+    bool use_single_keyed_cache) {
+  DCHECK(request);
+  const int64_t upload_data_identifier =
+      request->upload_data_stream ? request->upload_data_stream->identifier()
+                                  : int64_t(0);
+  return GenerateCacheKey(
+      request->url, request->load_flags, request->network_isolation_key,
+      upload_data_identifier, request->is_subframe_document_resource,
+      use_single_keyed_cache, request->checksum);
 }
 
 // static
@@ -577,61 +642,6 @@
   return ERR_IO_PENDING;
 }
 
-// static
-// Generate a key that can be used inside the cache.
-std::string HttpCache::GenerateCacheKey(const HttpRequestInfo* request,
-                                        bool use_single_keyed_cache) {
-  // The first character of the key may vary depending on whether or not sending
-  // credentials is permitted for this request. This only happens if the
-  // SplitCacheByIncludeCredentials feature is enabled, or if the single-keyed
-  // cache is enabled. The single-keyed cache must always be split by
-  // credentials in order to make coep:credentialless work safely.
-  const char credential_key =
-      ((base::FeatureList::IsEnabled(
-            features::kSplitCacheByIncludeCredentials) ||
-        use_single_keyed_cache) &&
-       (request->load_flags & LOAD_DO_NOT_SAVE_COOKIES))
-          ? '0'
-          : '1';
-
-  const int64_t post_key = request->upload_data_stream
-                               ? request->upload_data_stream->identifier()
-                               : int64_t(0);
-  std::string isolation_key;
-  if (use_single_keyed_cache) {
-    DCHECK(IsSplitCacheEnabled());
-    DCHECK(!request->checksum.empty());
-    DCHECK(!(request->load_flags &
-             (net::LOAD_VALIDATE_CACHE | net::LOAD_BYPASS_CACHE |
-              net::LOAD_SKIP_CACHE_VALIDATION | net::LOAD_ONLY_FROM_CACHE |
-              net::LOAD_DISABLE_CACHE | net::LOAD_SKIP_VARY_CHECK)));
-    isolation_key = base::StrCat(
-        {kSingleKeyPrefix, request->checksum, kSingleKeySeparator});
-  } else if (IsSplitCacheEnabled()) {
-    // Prepend the key with |kDoubleKeyPrefix| = "_dk_" to mark it as
-    // double-keyed (and makes it an invalid url so that it doesn't get
-    // confused with a single-keyed entry). Separate the origin and url
-    // with invalid whitespace character |kDoubleKeySeparator|.
-    DCHECK(request->network_isolation_key.IsFullyPopulated());
-    std::string subframe_document_resource_prefix =
-        request->is_subframe_document_resource ? kSubframeDocumentResourcePrefix
-                                               : "";
-    isolation_key = base::StrCat(
-        {kDoubleKeyPrefix, subframe_document_resource_prefix,
-         request->network_isolation_key.ToString(), kDoubleKeySeparator});
-  }
-
-  // The key format is:
-  // credential_key/post_key/[isolation_key]url
-
-  // Strip out the reference, username, and password sections of the URL and
-  // concatenate with the credential_key, the post_key, and the network
-  // isolation key if we are splitting the cache.
-  return base::StringPrintf("%c/%" PRId64 "/%s%s", credential_key, post_key,
-                            isolation_key.c_str(),
-                            HttpUtil::SpecForRequest(request->url).c_str());
-}
-
 void HttpCache::DoomActiveEntry(const std::string& key) {
   auto it = active_entries_.find(key);
   if (it == active_entries_.end())
@@ -708,7 +718,7 @@
   // single-keyed cache, so therefore it is correct that use_single_keyed_cache
   // be false.
   std::string key =
-      GenerateCacheKey(&temp_info, /*use_single_keyed_cache=*/false);
+      GenerateCacheKeyForRequest(&temp_info, /*use_single_keyed_cache=*/false);
 
   // Defer to DoomEntry if there is an active entry, otherwise call
   // AsyncDoomEntry without triggering a callback.
diff --git a/net/http/http_cache.h b/net/http/http_cache.h
index 3ac1f522..8bf7072 100644
--- a/net/http/http_cache.h
+++ b/net/http/http_cache.h
@@ -258,8 +258,18 @@
   // Get the URL from the entry's cache key.
   static std::string GetResourceURLFromHttpCacheKey(const std::string& key);
 
-  // Function to generate cache key for testing.
-  static std::string GenerateCacheKeyForTest(const HttpRequestInfo* request);
+  // Generates the cache key for a request.
+  static std::string GenerateCacheKey(
+      const GURL& url,
+      int load_flags,
+      const NetworkIsolationKey& network_isolation_key,
+      int64_t upload_data_identifier,
+      bool is_subframe_document_resource,
+      bool use_single_keyed_cache,
+      const std::string& single_key_checksum);
+  static std::string GenerateCacheKeyForRequest(
+      const HttpRequestInfo* request,
+      bool use_single_keyed_cache = false);
 
   // Enable split cache feature if not already overridden in the feature list.
   // Should only be invoked during process initialization before the HTTP
@@ -421,10 +431,6 @@
   // time after receiving the notification.
   int GetBackendForTransaction(Transaction* transaction);
 
-  // Generates the cache key for this request.
-  static std::string GenerateCacheKey(const HttpRequestInfo*,
-                                      bool use_single_keyed_cache);
-
   // Dooms the entry selected by |key|, if it is currently in the list of active
   // entries.
   void DoomActiveEntry(const std::string& key);
diff --git a/net/http/http_cache_transaction.cc b/net/http/http_cache_transaction.cc
index 5f4450b7..6d631ce 100644
--- a/net/http/http_cache_transaction.cc
+++ b/net/http/http_cache_transaction.cc
@@ -1042,7 +1042,7 @@
     // the entry was marked unusable and the transaction was restarted in
     //  DoCacheReadResponseComplete(), so it will no longer match the value in
     //  `request_`. So we pass it through explicitly.
-    cache_key_ = cache_->GenerateCacheKey(
+    cache_key_ = cache_->GenerateCacheKeyForRequest(
         request_, effective_load_flags_ & LOAD_USE_SINGLE_KEYED_CACHE);
 
     // Requested cache access mode.
diff --git a/net/http/http_cache_unittest.cc b/net/http/http_cache_unittest.cc
index c348c0d..854d01dc 100644
--- a/net/http/http_cache_unittest.cc
+++ b/net/http/http_cache_unittest.cc
@@ -825,7 +825,7 @@
     request_info.method = "GET";
     request_info.network_isolation_key = net::NetworkIsolationKey(site, site);
     MockHttpCache cache;
-    return cache.http_cache()->GenerateCacheKeyForTest(&request_info);
+    return cache.http_cache()->GenerateCacheKeyForRequest(&request_info);
   }
 };
 
@@ -5336,7 +5336,8 @@
   // Allow all requests to move from the Create queue to the active entry.
   // All would have been added to writers.
   base::RunLoop().RunUntilIdle();
-  std::string cache_key = cache.http_cache()->GenerateCacheKeyForTest(&request);
+  std::string cache_key =
+      cache.http_cache()->GenerateCacheKeyForRequest(&request);
   EXPECT_EQ(kNumTransactions, cache.GetCountWriterTransactions(cache_key));
 
   // The second transaction skipped validation, thus only one network
@@ -8305,7 +8306,8 @@
   // Simulate a previous transaction being cancelled.
   disk_cache::Entry* entry;
   MockHttpRequest request(transaction);
-  std::string cache_key = cache.http_cache()->GenerateCacheKeyForTest(&request);
+  std::string cache_key =
+      cache.http_cache()->GenerateCacheKeyForRequest(&request);
   ASSERT_TRUE(cache.OpenBackendEntry(cache_key, &entry));
   entry->CancelSparseIO();
 
diff --git a/net/http/http_transaction_test_util.cc b/net/http/http_transaction_test_util.cc
index 254263ab..e69433b 100644
--- a/net/http/http_transaction_test_util.cc
+++ b/net/http/http_transaction_test_util.cc
@@ -204,7 +204,7 @@
 }
 
 std::string MockHttpRequest::CacheKey() {
-  return HttpCache::GenerateCacheKeyForTest(this);
+  return HttpCache::GenerateCacheKeyForRequest(this);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/pdf/loader/chunk_stream.h b/pdf/loader/chunk_stream.h
index 94b5371..c3d012a 100644
--- a/pdf/loader/chunk_stream.h
+++ b/pdf/loader/chunk_stream.h
@@ -20,16 +20,16 @@
 
 // This class collects a chunks of data into one data stream. Client can check
 // if data in certain range is available, and get missing chunks of data.
-template <uint32_t N>
+template <size_t N>
 class ChunkStream {
  public:
-  static constexpr uint32_t kChunkSize = N;
+  static constexpr size_t kChunkSize = N;
   using ChunkData = typename std::array<unsigned char, N>;
 
   ChunkStream() {}
   ~ChunkStream() {}
 
-  void SetChunkData(uint32_t chunk_index, std::unique_ptr<ChunkData> data) {
+  void SetChunkData(size_t chunk_index, std::unique_ptr<ChunkData> data) {
     if (!data)
       return;
 
@@ -48,11 +48,11 @@
       return false;
 
     unsigned char* data_buffer = static_cast<unsigned char*>(buffer);
-    uint32_t start = range.start();
+    size_t start = range.start();
     while (start != range.end()) {
-      const uint32_t chunk_index = GetChunkIndex(start);
-      const uint32_t chunk_start = start % kChunkSize;
-      const uint32_t len =
+      const size_t chunk_index = GetChunkIndex(start);
+      const size_t chunk_start = start % kChunkSize;
+      const size_t len =
           std::min(kChunkSize - chunk_start, range.end() - start);
       memcpy(data_buffer, data_[chunk_index]->data() + chunk_start, len);
       data_buffer += len;
@@ -61,9 +61,9 @@
     return true;
   }
 
-  uint32_t GetChunkIndex(uint32_t offset) const { return offset / kChunkSize; }
+  size_t GetChunkIndex(size_t offset) const { return offset / kChunkSize; }
 
-  gfx::Range GetChunksRange(uint32_t offset, uint32_t size) const {
+  gfx::Range GetChunksRange(size_t offset, size_t size) const {
     return gfx::Range(GetChunkIndex(offset), GetChunkEnd(offset + size));
   }
 
@@ -81,12 +81,12 @@
     return filled_chunks_.Contains(chunks_range);
   }
 
-  bool IsChunkAvailable(uint32_t chunk_index) const {
+  bool IsChunkAvailable(size_t chunk_index) const {
     return filled_chunks_.Contains(chunk_index);
   }
 
-  void set_eof_pos(uint32_t eof_pos) { eof_pos_ = eof_pos; }
-  uint32_t eof_pos() const { return eof_pos_; }
+  void set_eof_pos(size_t eof_pos) { eof_pos_ = eof_pos; }
+  size_t eof_pos() const { return eof_pos_; }
 
   const RangeSet& filled_chunks() const { return filled_chunks_; }
 
@@ -94,7 +94,7 @@
     return eof_pos_ > 0 && IsRangeAvailable(gfx::Range(0, eof_pos_));
   }
 
-  bool IsValidChunkIndex(uint32_t chunk_index) const {
+  bool IsValidChunkIndex(size_t chunk_index) const {
     return !eof_pos_ || (chunk_index <= GetChunkIndex(eof_pos_ - 1));
   }
 
@@ -105,18 +105,18 @@
     filled_chunks_count_ = 0;
   }
 
-  uint32_t filled_chunks_count() const { return filled_chunks_count_; }
-  uint32_t total_chunks_count() const { return GetChunkEnd(eof_pos_); }
+  size_t filled_chunks_count() const { return filled_chunks_count_; }
+  size_t total_chunks_count() const { return GetChunkEnd(eof_pos_); }
 
  private:
-  uint32_t GetChunkEnd(uint32_t offset) const {
+  size_t GetChunkEnd(size_t offset) const {
     return (offset + kChunkSize - 1) / kChunkSize;
   }
 
   std::vector<std::unique_ptr<ChunkData>> data_;
-  uint32_t eof_pos_ = 0;
+  size_t eof_pos_ = 0;
   RangeSet filled_chunks_;
-  uint32_t filled_chunks_count_ = 0;
+  size_t filled_chunks_count_ = 0;
 };
 
 }  // namespace chrome_pdf
diff --git a/pdf/loader/document_loader_impl.cc b/pdf/loader/document_loader_impl.cc
index 8702c96d..26a7907e 100644
--- a/pdf/loader/document_loader_impl.cc
+++ b/pdf/loader/document_loader_impl.cc
@@ -218,7 +218,7 @@
   DCHECK(!IsDocumentComplete());
   DCHECK_GT(GetDocumentSize(), 0U);
 
-  const uint32_t range_start =
+  const size_t range_start =
       pending_requests_.IsEmpty() ? 0 : pending_requests_.First().start();
   RangeSet candidates_for_request(
       gfx::Range(range_start, chunk_stream_.total_chunks_count()));
@@ -243,8 +243,8 @@
   chunk_.Clear();
   is_partial_loader_active_ = true;
 
-  const uint32_t start = next_request.start() * DataStream::kChunkSize;
-  const uint32_t length =
+  const size_t start = next_request.start() * DataStream::kChunkSize;
+  const size_t length =
       std::min(GetDocumentSize() - start,
                next_request.length() * DataStream::kChunkSize);
 
@@ -330,8 +330,8 @@
     if (chunk_.data_size == 0)
       chunk_.chunk_data = std::make_unique<DataStream::ChunkData>();
 
-    const uint32_t new_chunk_data_len =
-        std::min(DataStream::kChunkSize - chunk_.data_size, input_size);
+    const size_t new_chunk_data_len =
+        std::min(DataStream::kChunkSize - chunk_.data_size, size_t{input_size});
     memcpy(chunk_.chunk_data->data() + chunk_.data_size, input,
            new_chunk_data_len);
     chunk_.data_size += new_chunk_data_len;
@@ -379,7 +379,7 @@
     if (chunk_.data_size != 0)
       SaveChunkData();
   } else {
-    uint32_t eof = EndOfCurrentChunk();
+    size_t eof = EndOfCurrentChunk();
     if (!chunk_stream_.filled_chunks().IsEmpty()) {
       eof = std::max(
           chunk_stream_.filled_chunks().Last().end() * DataStream::kChunkSize,
diff --git a/services/network/first_party_sets/first_party_sets_manager.cc b/services/network/first_party_sets/first_party_sets_manager.cc
index f471610..a3c812e1 100644
--- a/services/network/first_party_sets/first_party_sets_manager.cc
+++ b/services/network/first_party_sets/first_party_sets_manager.cc
@@ -348,13 +348,11 @@
   FirstPartySetsManager::SetsByOwner sets;
   for (const auto& pair : *sets_) {
     const net::SchemefulSite& member = pair.first;
-    const net::SchemefulSite& owner = pair.second;
-    auto set = sets.find(owner);
-    if (set == sets.end()) {
-      sets.emplace(owner, std::initializer_list<net::SchemefulSite>{member});
-    } else {
-      set->second.insert(member);
-    }
+    net::SchemefulSite owner = pair.second;
+    auto set = sets.emplace(std::make_pair(std::move(owner),
+                                           std::set<net::SchemefulSite>()))
+                   .first;
+    set->second.insert(member);
   }
 
   return sets;
diff --git a/services/network/http_cache_data_remover_unittest.cc b/services/network/http_cache_data_remover_unittest.cc
index e10dc09..30118548 100644
--- a/services/network/http_cache_data_remover_unittest.cc
+++ b/services/network/http_cache_data_remover_unittest.cc
@@ -123,7 +123,7 @@
     request_info.method = "GET";
     request_info.network_isolation_key =
         net::NetworkIsolationKey(kOrigin, kOrigin);
-    return cache_->GenerateCacheKeyForTest(&request_info);
+    return cache_->GenerateCacheKeyForRequest(&request_info);
   }
 
   void RemoveData(mojom::ClearDataFilterPtr filter,
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 47e3bba3..9249ae84 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -1775,8 +1775,8 @@
             is_subframe_document_resource;
         request_info.network_isolation_key = isolation_key;
         disk_cache::EntryResult result = backend->OpenOrCreateEntry(
-            net::HttpCache::GenerateCacheKeyForTest(&request_info), net::LOWEST,
-            base::BindOnce([](disk_cache::EntryResult) {}));
+            net::HttpCache::GenerateCacheKeyForRequest(&request_info),
+            net::LOWEST, base::BindOnce([](disk_cache::EntryResult) {}));
         ASSERT_EQ(result.net_error(), net::OK);
 
         disk_cache::ScopedEntryPtr entry(result.ReleaseEntry());
diff --git a/services/network/resource_scheduler/resource_scheduler_unittest.cc b/services/network/resource_scheduler/resource_scheduler_unittest.cc
index cffb2c5a..f61e3de 100644
--- a/services/network/resource_scheduler/resource_scheduler_unittest.cc
+++ b/services/network/resource_scheduler/resource_scheduler_unittest.cc
@@ -522,7 +522,7 @@
     request_info.network_isolation_key =
         net::IsolationInfo().network_isolation_key();
     request_info.is_subframe_document_resource = false;
-    std::string key = net::HttpCache::GenerateCacheKeyForTest(&request_info);
+    std::string key = net::HttpCache::GenerateCacheKeyForRequest(&request_info);
 
     TestEntryResultCompletionCallback create_entry_callback;
     disk_cache::EntryResult result = backend->OpenOrCreateEntry(
diff --git a/services/viz/privileged/cpp/overlay_strategy_mojom_traits.h b/services/viz/privileged/cpp/overlay_strategy_mojom_traits.h
index b9fbc7d1..5d8310b 100644
--- a/services/viz/privileged/cpp/overlay_strategy_mojom_traits.h
+++ b/services/viz/privileged/cpp/overlay_strategy_mojom_traits.h
@@ -6,6 +6,7 @@
 #define SERVICES_VIZ_PRIVILEGED_CPP_OVERLAY_STRATEGY_MOJOM_TRAITS_H_
 
 #include "base/notreached.h"
+#include "components/viz/common/buildflags.h"
 #include "components/viz/common/display/overlay_strategy.h"
 #include "services/viz/privileged/mojom/compositing/overlay_strategy.mojom-shared.h"
 
@@ -21,8 +22,10 @@
         return viz::mojom::OverlayStrategy::kSingleOnTop;
       case viz::OverlayStrategy::kUnderlay:
         return viz::mojom::OverlayStrategy::kUnderlay;
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
       case viz::OverlayStrategy::kUnderlayCast:
         return viz::mojom::OverlayStrategy::kUnderlayCast;
+#endif
       default:
         break;
     }
@@ -42,9 +45,11 @@
       case viz::mojom::OverlayStrategy::kUnderlay:
         *out = viz::OverlayStrategy::kUnderlay;
         return true;
+#if BUILDFLAG(ENABLE_CAST_OVERLAY_STRATEGY)
       case viz::mojom::OverlayStrategy::kUnderlayCast:
         *out = viz::OverlayStrategy::kUnderlayCast;
         return true;
+#endif
     }
     return false;
   }
diff --git a/services/viz/privileged/mojom/compositing/BUILD.gn b/services/viz/privileged/mojom/compositing/BUILD.gn
index 179c125c..99529e9 100644
--- a/services/viz/privileged/mojom/compositing/BUILD.gn
+++ b/services/viz/privileged/mojom/compositing/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 import("//build/config/ui.gni")
+import("//components/viz/viz.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
 
 mojom("compositing") {
@@ -39,6 +40,9 @@
   if (use_ozone) {
     enabled_features += [ "use_ozone" ]
   }
+  if (enable_cast_overlay_strategy) {
+    enabled_features += [ "enable_cast_overlay_strategy" ]
+  }
 
   cpp_typemaps = [
     {
diff --git a/services/viz/privileged/mojom/compositing/overlay_strategy.mojom b/services/viz/privileged/mojom/compositing/overlay_strategy.mojom
index a98cc61..71c1f41 100644
--- a/services/viz/privileged/mojom/compositing/overlay_strategy.mojom
+++ b/services/viz/privileged/mojom/compositing/overlay_strategy.mojom
@@ -12,5 +12,7 @@
   kFullscreen,
   kSingleOnTop,
   kUnderlay,
+
+  [EnableIf=enable_cast_overlay_strategy]
   kUnderlayCast,
 };
diff --git a/services/viz/privileged/mojom/gl/BUILD.gn b/services/viz/privileged/mojom/gl/BUILD.gn
index 6572a57b1..d933a57 100644
--- a/services/viz/privileged/mojom/gl/BUILD.gn
+++ b/services/viz/privileged/mojom/gl/BUILD.gn
@@ -14,6 +14,8 @@
     "gpu_service.mojom",
   ]
 
+  parser_deps = [ "//components/viz/common:buildflags" ]
+
   public_deps = [
     "//gpu/ipc/common:interfaces",
     "//media/mojo/mojom",
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index c8c35b7..62bb4140 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1934,7 +1934,7 @@
       {
         "args": [],
         "cros_board": "atlas",
-        "cros_img": "atlas-release/R104-14909.7.0",
+        "cros_img": "atlas-release/R104-14909.26.0",
         "name": "lacros_all_tast_tests ATLAS_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -1998,7 +1998,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R104-14909.11.0",
+        "cros_img": "eve-release/R104-14909.26.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2107,7 +2107,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.11.0",
+        "cros_img": "hana-release/R104-14909.26.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2171,7 +2171,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.11.0",
+        "cros_img": "jacuzzi-release/R104-14909.26.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_DEV",
         "resultdb": {
           "enable": true,
@@ -2218,7 +2218,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.11.0",
+        "cros_img": "hana-release/R104-14909.26.0",
         "name": "ozone_unittests HANA_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2270,7 +2270,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.ozone_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.11.0",
+        "cros_img": "jacuzzi-release/R104-14909.26.0",
         "name": "ozone_unittests JACUZZI_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -2309,7 +2309,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "hana",
-        "cros_img": "hana-release/R104-14909.11.0",
+        "cros_img": "hana-release/R104-14909.26.0",
         "name": "viz_unittests HANA_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
@@ -2361,7 +2361,7 @@
           "--test-launcher-filter-file=../../testing/buildbot/filters/lacros-arm.viz_unittests.filter"
         ],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R104-14909.11.0",
+        "cros_img": "jacuzzi-release/R104-14909.26.0",
         "name": "viz_unittests JACUZZI_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 4dd2908..4bbe94e1 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -2889,7 +2889,8 @@
         "args": [
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
-          "--avd-config=../../tools/android/avd/proto/generic_android24.textpb"
+          "--avd-config=../../tools/android/avd/proto/generic_android24.textpb",
+          "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter"
         ],
         "isolate_profile_data": true,
         "merge": {
@@ -8327,15 +8328,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8361,7 +8362,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8412,15 +8413,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8446,7 +8447,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8837,15 +8838,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8871,7 +8872,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -8922,15 +8923,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -8956,7 +8957,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 5f88b46..3e96976 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -46457,15 +46457,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46491,7 +46491,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46542,15 +46542,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -46576,7 +46576,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -46967,15 +46967,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47001,7 +47001,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47052,15 +47052,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47086,7 +47086,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47481,15 +47481,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47515,7 +47515,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47566,15 +47566,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -47600,7 +47600,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -47991,15 +47991,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48025,7 +48025,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48076,15 +48076,15 @@
       {
         "args": [
           "--additional-apk=apks/ChromePublic.apk",
+          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/AOSP_SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48110,7 +48110,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48573,15 +48573,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48607,7 +48607,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -48658,15 +48658,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -48692,7 +48692,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49083,15 +49083,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49117,7 +49117,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49168,15 +49168,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49202,7 +49202,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49665,15 +49665,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M103/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M103/out/Release",
           "--client-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49699,7 +49699,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -49750,15 +49750,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
+          "--client-outdir",
+          "../../weblayer_instrumentation_test_M104/out/Release",
           "--implementation-outdir",
           ".",
           "--test-expectations",
           "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
-          "--client-outdir",
-          "../../weblayer_instrumentation_test_M104/out/Release",
           "--client-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -49784,7 +49784,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50175,15 +50175,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M103/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=103",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50209,7 +50209,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M103",
-              "revision": "version:103.0.5060.68"
+              "revision": "version:103.0.5060.79"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
@@ -50260,15 +50260,15 @@
       {
         "args": [
           "--additional-apk=apks/WebLayerShellSystemWebView.apk",
+          "--webview-apk-path=apks/SystemWebView.apk",
           "--test-runner-outdir",
           ".",
           "--client-outdir",
           ".",
-          "--test-expectations",
-          "../../weblayer/browser/android/javatests/skew/expectations.txt",
-          "--webview-apk-path=apks/SystemWebView.apk",
           "--implementation-outdir",
           "../../weblayer_instrumentation_test_M104/out/Release",
+          "--test-expectations",
+          "../../weblayer/browser/android/javatests/skew/expectations.txt",
           "--impl-version=104",
           "--gs-results-bucket=chromium-result-details",
           "--recover-devices",
@@ -50294,7 +50294,7 @@
             {
               "cipd_package": "chromium/testing/weblayer-x86",
               "location": "weblayer_instrumentation_test_M104",
-              "revision": "version:104.0.5112.27"
+              "revision": "version:104.0.5112.28"
             },
             {
               "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index a7573a7..2885b47 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -5656,21 +5656,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -5683,7 +5683,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -5822,21 +5822,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -5848,7 +5848,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -5968,21 +5968,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -5994,7 +5994,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index bcb5322..a2676af7 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -92884,21 +92884,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -92906,7 +92906,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -93020,28 +93020,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -93141,28 +93141,28 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -94494,20 +94494,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -94521,7 +94521,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -94660,20 +94660,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -94686,7 +94686,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -94806,20 +94806,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -94832,7 +94832,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -96327,20 +96327,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -96354,7 +96354,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -96493,20 +96493,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -96519,7 +96519,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -96639,20 +96639,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -96665,7 +96665,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -97400,20 +97400,20 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -97426,7 +97426,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
diff --git a/testing/buildbot/chromium.memory.json b/testing/buildbot/chromium.memory.json
index e42187f..70ac681 100644
--- a/testing/buildbot/chromium.memory.json
+++ b/testing/buildbot/chromium.memory.json
@@ -19053,21 +19053,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.filter;../../testing/buildbot/filters/linux-lacros.interactive_ui_tests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.9",
+        "name": "interactive_ui_tests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -19080,7 +19080,7 @@
         },
         "test": "interactive_ui_tests",
         "test_id_prefix": "ninja://chrome/test:interactive_ui_tests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -19219,21 +19219,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -19245,7 +19245,7 @@
         },
         "test": "lacros_chrome_browsertests",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
@@ -19365,21 +19365,21 @@
       {
         "args": [
           "--test-launcher-filter-file=../../testing/buildbot/filters/linux-lacros.lacros_chrome_browsertests.skew.filter",
-          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome"
+          "--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome"
         ],
         "isolate_profile_data": true,
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_gtest_merge.py"
         },
-        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.9",
+        "name": "lacros_chrome_browsertests_run_in_series Lacros version skew testing ash 104.0.5112.23",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
             {
               "cipd_package": "chromium/testing/linux-ash-chromium/x86_64/ash.zip",
-              "location": "lacros_version_skew_tests_v104.0.5112.9",
-              "revision": "version:104.0.5112.9"
+              "location": "lacros_version_skew_tests_v104.0.5112.23",
+              "revision": "version:104.0.5112.23"
             }
           ],
           "dimension_sets": [
@@ -19391,7 +19391,7 @@
         },
         "test": "lacros_chrome_browsertests_run_in_series",
         "test_id_prefix": "ninja://chrome/test:lacros_chrome_browsertests_run_in_series/",
-        "variant_id": "Lacros version skew testing ash 104.0.5112.9"
+        "variant_id": "Lacros version skew testing ash 104.0.5112.23"
       },
       {
         "args": [
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn
index f6c44f55..b852a54 100644
--- a/testing/buildbot/filters/BUILD.gn
+++ b/testing/buildbot/filters/BUILD.gn
@@ -36,6 +36,12 @@
   ]
 }
 
+source_set("blink_platform_unittests") {
+  testonly = true
+
+  data = [ "//testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter" ]
+}
+
 source_set("blink_unittests_filters") {
   testonly = true
 
diff --git a/testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter b/testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter
new file mode 100644
index 0000000..da67c4f
--- /dev/null
+++ b/testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter
@@ -0,0 +1,6 @@
+# https://crbug.com/1254869
+-HarfBuzzShaperTest.IdeographicSpace
+
+# https://crbug.com/1108121
+-HarfBuzzShaperTest.ShapeHorizontalWithSubpixelPositionWithoutKerningIsNotRounded
+-HarfBuzzShaperTest.ShapeHorizontalWithoutSubpixelPositionWithKerningIsRounded
\ No newline at end of file
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index 49e88726..c014574 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1050,7 +1050,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.11.0",
+        "cros_img": "octopus-release/R104-14909.26.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1098,7 +1098,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.11.0",
+        "cros_img": "octopus-release/R104-14909.26.0",
         "name": "lacros_variations_tast_tests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"name:lacros.VariationSmoke\")",
@@ -1145,7 +1145,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R104-14909.11.0",
+        "cros_img": "octopus-release/R104-14909.26.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1198,7 +1198,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.11.0",
+        "cros_img": "strongbad-release/R104-14909.26.0",
         "name": "lacros_all_tast_tests strongbad_RELEASE_DEV",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1245,7 +1245,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.11.0",
+        "cros_img": "strongbad-release/R104-14909.26.0",
         "name": "ozone_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1289,7 +1289,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R104-14909.11.0",
+        "cros_img": "strongbad-release/R104-14909.26.0",
         "name": "viz_unittests strongbad_RELEASE_DEV",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index e852705..536ae16 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -205,6 +205,12 @@
   },
   'blink_platform_unittests': {
     'modifications': {
+      # TODO(crbug.com/1303439): Remove this filter
+      'android-nougat-x86-rel': {
+        'args': [
+          '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_n.blink_platform_unittests.filter',
+        ],
+      },
       'android-pie-arm64-rel': {
         # TODO(crbug.com/1111436): Move this back to walleye if/when additional
         # capacity has been deployed.
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 6396d317c..0223c3d 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -37,15 +37,15 @@
   },
   'LACROS_VERSION_SKEW_DEV': {
     'args': [
-      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.9/test_ash_chrome',
+      '--ash-chrome-path-override=../../lacros_version_skew_tests_v104.0.5112.23/test_ash_chrome',
     ],
-    'identifier': 'Lacros version skew testing ash 104.0.5112.9',
+    'identifier': 'Lacros version skew testing ash 104.0.5112.23',
     'swarming': {
       'cipd_packages': [
         {
           'cipd_package': 'chromium/testing/linux-ash-chromium/x86_64/ash.zip',
-          'location': 'lacros_version_skew_tests_v104.0.5112.9',
-          'revision': 'version:104.0.5112.9',
+          'location': 'lacros_version_skew_tests_v104.0.5112.23',
+          'revision': 'version:104.0.5112.23',
         },
       ],
     },
@@ -529,16 +529,16 @@
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -546,23 +546,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.27'
+          'revision': 'version:104.0.5112.28',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/AOSP_SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -570,10 +570,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.68'
+          'revision': 'version:103.0.5060.79',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_10_AND_M_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -673,16 +673,16 @@
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M104/out/Release',
-      '--impl-version=104'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=104',
     ],
     'identifier': 'with_impl_from_104',
     'swarming': {
@@ -690,23 +690,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.27'
+          'revision': 'version:104.0.5112.28',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
       '--client-outdir',
       '.',
-      '--test-expectations',
-      '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
       '--implementation-outdir',
       '../../weblayer_instrumentation_test_M103/out/Release',
-      '--impl-version=103'
+      '--test-expectations',
+      '../../weblayer/browser/android/javatests/skew/expectations.txt',
+      '--impl-version=103',
     ],
     'identifier': 'with_impl_from_103',
     'swarming': {
@@ -714,10 +714,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.68'
+          'revision': 'version:103.0.5060.79',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_IMPL_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -817,16 +817,16 @@
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M104/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M104/out/Release',
-      '--client-version=104'
+      '--client-version=104',
     ],
     'identifier': 'with_client_from_104',
     'swarming': {
@@ -834,23 +834,23 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M104',
-          'revision': 'version:104.0.5112.27'
+          'revision': 'version:104.0.5112.28',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_ONE_MILESTONE': {
     'args': [
+      '--webview-apk-path=apks/SystemWebView.apk',
       '--test-runner-outdir',
       '.',
+      '--client-outdir',
+      '../../weblayer_instrumentation_test_M103/out/Release',
       '--implementation-outdir',
       '.',
       '--test-expectations',
       '../../weblayer/browser/android/javatests/skew/expectations.txt',
-      '--webview-apk-path=apks/SystemWebView.apk',
-      '--client-outdir',
-      '../../weblayer_instrumentation_test_M103/out/Release',
-      '--client-version=103'
+      '--client-version=103',
     ],
     'identifier': 'with_client_from_103',
     'swarming': {
@@ -858,10 +858,10 @@
         {
           'cipd_package': 'chromium/testing/weblayer-x86',
           'location': 'weblayer_instrumentation_test_M103',
-          'revision': 'version:103.0.5060.68'
+          'revision': 'version:103.0.5060.79',
         }
-      ]
-    }
+      ],
+    },
   },
   'WEBLAYER_CLIENT_SKEW_TESTS_NTH_MINUS_TWO_MILESTONE': {
     'args': [
@@ -971,8 +971,8 @@
   'CROS_ATLAS_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'atlas',
-      'cros_chrome_version': '104.0.5112.6',
-      'cros_img': 'atlas-release/R104-14909.7.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'atlas-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'ATLAS_RELEASE_DEV',
@@ -1007,8 +1007,8 @@
   'CROS_EVE_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '104.0.5112.9',
-      'cros_img': 'eve-release/R104-14909.11.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'eve-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_DEV',
@@ -1052,8 +1052,8 @@
   'CROS_HANA_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '104.0.5112.9',
-      'cros_img': 'hana-release/R104-14909.11.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'hana-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_DEV',
@@ -1088,8 +1088,8 @@
   'CROS_JACUZZI_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '104.0.5112.9',
-      'cros_img': 'jacuzzi-release/R104-14909.11.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'jacuzzi-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_DEV',
@@ -1124,8 +1124,8 @@
   'CROS_OCTOPUS_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '104.0.5112.9',
-      'cros_img': 'octopus-release/R104-14909.11.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'octopus-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_DEV',
@@ -1160,8 +1160,8 @@
   'CROS_STRONGBAD_RELEASE_DEV': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '104.0.5112.9',
-      'cros_img': 'strongbad-release/R104-14909.11.0',
+      'cros_chrome_version': '104.0.5112.23',
+      'cros_img': 'strongbad-release/R104-14909.26.0',
     },
     'enabled': True,
     'identifier': 'strongbad_RELEASE_DEV',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 703da39..d2e1e5d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1107,7 +1107,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_500ms",
+                    "name": "Enabled_20220625",
                     "params": {
                         "duration": "500ms"
                     },
@@ -3948,6 +3948,42 @@
             ]
         }
     ],
+    "FeedPositionAndroid": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_Feed_Position_Push_Down_Small_1",
+                    "params": {
+                        "push_down_feed_small": "true"
+                    },
+                    "enable_features": [
+                        "FeedPositionAndroid"
+                    ]
+                },
+                {
+                    "name": "Enabled_Feed_Position_Push_Down_Large_1",
+                    "params": {
+                        "push_down_feed_large": "true"
+                    },
+                    "enable_features": [
+                        "FeedPositionAndroid"
+                    ]
+                },
+                {
+                    "name": "Enabled_Feed_Position_Pull_Up_1",
+                    "params": {
+                        "pull_up_feed": "true"
+                    },
+                    "enable_features": [
+                        "FeedPositionAndroid"
+                    ]
+                }
+            ]
+        }
+    ],
     "FeedPullToRefreshIph": [
         {
             "platforms": [
@@ -5241,7 +5277,19 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled",
+                    "name": "EnabledWithOnDemandReactions",
+                    "params": {
+                        "should_load_reactions_on_demand": "true"
+                    },
+                    "enable_features": [
+                        "LightweightReactions"
+                    ]
+                },
+                {
+                    "name": "EnabledWithPreloadedReactions",
+                    "params": {
+                        "should_load_reactions_on_demand": "false"
+                    },
                     "enable_features": [
                         "LightweightReactions"
                     ]
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 9d8a9be..e80a356 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1286,18 +1286,6 @@
     View()->SetNeedsLayout();
 }
 
-void LocalFrame::DeviceScaleFactorChanged() {
-  GetDocument()->MediaQueryAffectingValueChanged(MediaValueChange::kOther);
-  GetDocument()->GetStyleEngine().MarkViewportStyleDirty();
-  GetDocument()->GetStyleEngine().MarkAllElementsForStyleRecalc(
-      StyleChangeReasonForTracing::Create(style_change_reason::kZoom));
-  for (Frame* child = Tree().FirstChild(); child;
-       child = child->Tree().NextSibling()) {
-    if (auto* child_local_frame = DynamicTo<LocalFrame>(child))
-      child_local_frame->DeviceScaleFactorChanged();
-  }
-}
-
 void LocalFrame::MediaQueryAffectingValueChangedForLocalSubtree(
     MediaValueChange value) {
   GetDocument()->MediaQueryAffectingValueChanged(value);
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 669d4ec..ba6e2a7 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -357,7 +357,6 @@
   void SetPageAndTextZoomFactors(float page_zoom_factor,
                                  float text_zoom_factor);
 
-  void DeviceScaleFactorChanged();
   double DevicePixelRatio() const;
 
   // Informs the local root's document and its local descendant subtree that a
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
index e3a7e41..b222ff2ef 100644
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
@@ -83,10 +83,10 @@
     "JavaScriptExecuteRequestInIsolatedWorld gets an invalid world id.";
 
 #if BUILDFLAG(IS_MAC)
-uint32_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
+size_t GetCurrentCursorPositionInFrame(LocalFrame* local_frame) {
   blink::WebRange range =
       WebLocalFrameImpl::FromFrame(local_frame)->SelectionRange();
-  return range.IsNull() ? 0U : static_cast<uint32_t>(range.StartOffset());
+  return range.IsNull() ? size_t{0} : static_cast<size_t>(range.StartOffset());
 }
 #endif
 
@@ -1155,12 +1155,13 @@
     if (!pepper_has_caret) {
       // When request range is invalid we will try to obtain it from current
       // frame selection. The fallback value will be 0.
-      uint32_t start = range.IsValid()
+      size_t start = range.IsValid()
                            ? range.start()
                            : GetCurrentCursorPositionInFrame(frame_);
 
       WebLocalFrameImpl::FromFrame(frame_)->FirstRectForCharacterRange(
-          start, range.length(), rect);
+          base::checked_cast<unsigned>(start),
+          base::checked_cast<unsigned>(range.length()), rect);
     }
   }
 
@@ -1173,7 +1174,8 @@
   gfx::Point baseline_point;
   ui::mojom::blink::AttributedStringPtr attributed_string = nullptr;
   NSAttributedString* string = SubstringUtil::AttributedSubstringInRange(
-      frame_, range.start(), range.length(), &baseline_point);
+      frame_, base::checked_cast<WTF::wtf_size_t>(range.start()),
+      base::checked_cast<WTF::wtf_size_t>(range.length()), &baseline_point);
   if (string)
     attributed_string = ui::mojom::blink::AttributedString::From(string);
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index fbe8754b..52a07bb 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -3361,7 +3361,8 @@
   return controller->SetComposition(
       text, ime_text_spans,
       replacement_range.IsValid()
-          ? WebRange(replacement_range.start(), replacement_range.length())
+          ? WebRange(base::checked_cast<int>(replacement_range.start()),
+                     base::checked_cast<int>(replacement_range.length()))
           : WebRange(),
       selection_start, selection_end);
 }
@@ -3377,7 +3378,8 @@
   controller->CommitText(
       text, ime_text_spans,
       replacement_range.IsValid()
-          ? WebRange(replacement_range.start(), replacement_range.length())
+          ? WebRange(base::checked_cast<int>(replacement_range.start()),
+                     base::checked_cast<int>(replacement_range.length()))
           : WebRange(),
       relative_cursor_pos);
 }
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index 6cc5f5b..195ae66 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -909,33 +909,17 @@
        border_spacing.inline_size * 2)
           .ClampNegativeToZero();
 
-  struct RepeatedFooter {
-    STACK_ALLOCATED();
-
-   public:
-    RepeatedFooter(wtf_size_t section_idx,
-                   LayoutUnit block_size,
-                   const NGBlockBreakToken* incoming_break_token)
-        : section_idx(section_idx),
-          block_size(block_size),
-          incoming_break_token(incoming_break_token) {}
-
-    wtf_size_t section_idx;  // Index into |sections|.
-    LayoutUnit block_size;
-    const NGBlockBreakToken* incoming_break_token;
-  };
-
   enum ESectionRepeatMode { kNotRepeated, kMayRepeatAgain, kRepeatedLast };
 
   auto CreateSectionConstraintSpace = [&table_writing_direction,
                                        &section_available_inline_size,
-                                       &constraint_space_data, &sections, this](
-                                          const NGBlockNode& section,
-                                          LayoutUnit block_offset,
-                                          wtf_size_t section_index,
-                                          const absl::optional<RepeatedFooter>
-                                              repeated_footer,
-                                          ESectionRepeatMode repeat_mode) {
+                                       &constraint_space_data, &sections,
+                                       this](const NGBlockNode& section,
+                                             LayoutUnit block_offset,
+                                             wtf_size_t section_index,
+                                             absl::optional<LayoutUnit>
+                                                 repeated_footer_block_size,
+                                             ESectionRepeatMode repeat_mode) {
     NGConstraintSpaceBuilder section_space_builder(
         ConstraintSpace(), table_writing_direction, /* is_new_fc */ true);
 
@@ -963,11 +947,11 @@
           /* is_new_fc */ true,
           container_builder_.RequiresContentBeforeBreaking());
 
-      if (repeated_footer) {
+      if (repeated_footer_block_size) {
         // Reserve space for the repeated footer at the block-end of the
         // fragmentainer. No other section may extend into this area.
         section_space_builder.ReserveSpaceAtFragmentainerEnd(
-            repeated_footer->block_size);
+            *repeated_footer_block_size);
       }
     }
 
@@ -1003,7 +987,7 @@
   absl::optional<LayoutUnit> table_baseline;
 
   bool has_repeated_header = false;
-  absl::optional<RepeatedFooter> pending_repeated_footer;
+  absl::optional<LayoutUnit> pending_repeated_footer_block_size;
 
   if (ConstraintSpace().HasKnownFragmentainerBlockSize() &&
       (grouped_children.header || grouped_children.footer)) {
@@ -1038,9 +1022,8 @@
         DCHECK_EQ(child, grouped_children.footer);
         // We need to reserve space for the repeated footer at the end of the
         // fragmentainer.
-        pending_repeated_footer.emplace(entry.GetSectionIndex(),
-                                        block_size + border_spacing.block_size,
-                                        entry.GetBreakToken());
+        pending_repeated_footer_block_size =
+            block_size + border_spacing.block_size;
       }
     }
   }
@@ -1144,25 +1127,25 @@
       LayoutUnit offset_for_childless_section = child_block_offset;
       child_block_offset += collapsible_border_spacing;
 
-      is_repeated_section =
-          (pending_repeated_footer && child == grouped_children.footer) ||
-          (has_repeated_header && child == grouped_children.header);
-
       bool may_repeat_again = false;
-      if (is_repeated_section) {
-        if (child == grouped_children.header) {
+      if (child == grouped_children.header) {
+        if (has_repeated_header) {
+          is_repeated_section = true;
           // Unless we've already been at the end, we cannot tell whether this
           // is the last time the header will repeat. We will tentatively have
           // to make it repeatable. If this turns out to be wrong, because we
           // reach the end in this fragment, we need to abort and relayout.
           may_repeat_again = !is_known_to_be_last_table_box_;
-        } else if (child == grouped_children.footer) {
+        }
+      } else if (child == grouped_children.footer) {
+        if (pending_repeated_footer_block_size) {
+          is_repeated_section = true;
           // For footers it's easier, though. Since we got all the way to the
           // footer during layout, this means that this will be the last time
           // the footer is repeated. We can finish it right away, unless we have
           // a repeated header as well (which means that we're going to
           // relayout).
-          pending_repeated_footer.reset();
+          pending_repeated_footer_block_size.reset();
           may_repeat_again =
               !is_known_to_be_last_table_box_ && has_repeated_header;
         }
@@ -1174,7 +1157,7 @@
 
       NGConstraintSpace child_space = CreateSectionConstraintSpace(
           child, child_block_offset, entry.GetSectionIndex(),
-          pending_repeated_footer, repeat_mode);
+          pending_repeated_footer_block_size, repeat_mode);
       if (is_repeated_section) {
         child_result =
             child.LayoutRepeatableRoot(child_space, child_break_token);
@@ -1288,7 +1271,7 @@
         NGLayoutResult::kNeedsRelayoutAsLastTableBox);
   }
 
-  if (pending_repeated_footer && table_box_extent) {
+  if (pending_repeated_footer_block_size && table_box_extent) {
     DCHECK(table_box_will_continue);
     // We broke before we got to the footer. Add it now. Before doing that,
     // though, also insert break tokens for the sections that we didn't get to
@@ -1309,11 +1292,10 @@
 
     LogicalOffset offset(section_inline_offset, child_block_offset);
     NGConstraintSpace child_space = CreateSectionConstraintSpace(
-        grouped_children.footer, offset.block_offset,
-        pending_repeated_footer->section_idx,
-        /* repeated_footer */ absl::nullopt, kMayRepeatAgain);
+        grouped_children.footer, offset.block_offset, entry.GetSectionIndex(),
+        /* repeated_footer_block_size */ absl::nullopt, kMayRepeatAgain);
     const NGLayoutResult* result = grouped_children.footer.LayoutRepeatableRoot(
-        child_space, pending_repeated_footer->incoming_break_token);
+        child_space, entry.GetBreakToken());
 
     LayoutUnit fragmentainer_block_offset =
         ConstraintSpace().FragmentainerOffsetAtBfc() + offset.block_offset;
@@ -1330,7 +1312,7 @@
       // normally fits (it should only be a quarter of the fragmentainer's
       // block-size), if the table box starts near the end of the fragmentainer,
       // we may still run out of space before a repeatable footer.
-      DCHECK(!pending_repeated_footer->incoming_break_token);
+      DCHECK(!entry.GetBreakToken());
     }
   }
 
diff --git a/third_party/blink/renderer/modules/content_index/content_index.cc b/third_party/blink/renderer/modules/content_index/content_index.cc
index f1b3d3f1..568f479 100644
--- a/third_party/blink/renderer/modules/content_index/content_index.cc
+++ b/third_party/blink/renderer/modules/content_index/content_index.cc
@@ -94,6 +94,14 @@
     return ScriptPromise();
   }
 
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  if (execution_context->IsInFencedFrame()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotAllowedError,
+        "ContentIndex is not allowed in fenced frames.");
+    return ScriptPromise();
+  }
+
   WTF::String description_error =
       ValidateDescription(*description, registration_.Get());
   if (!description_error.IsNull()) {
@@ -233,6 +241,14 @@
     return ScriptPromise();
   }
 
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  if (execution_context->IsInFencedFrame()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotAllowedError,
+        "ContentIndex is not allowed in fenced frames.");
+    return ScriptPromise();
+  }
+
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
@@ -275,6 +291,14 @@
     return ScriptPromise();
   }
 
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  if (execution_context->IsInFencedFrame()) {
+    exception_state.ThrowDOMException(
+        DOMExceptionCode::kNotAllowedError,
+        "ContentIndex is not allowed in fenced frames.");
+    return ScriptPromise();
+  }
+
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data.idl b/third_party/blink/renderer/modules/webcodecs/audio_data.idl
index 17ae2889..74cc0a2 100644
--- a/third_party/blink/renderer/modules/webcodecs/audio_data.idl
+++ b/third_party/blink/renderer/modules/webcodecs/audio_data.idl
@@ -5,6 +5,7 @@
 // https://github.com/WICG/web-codecs
 [
     Exposed=(Window,DedicatedWorker),
+    Serializable,
     RuntimeEnabled=WebCodecs
 ] interface AudioData {
   [RaisesException] constructor(AudioDataInit init);
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index bc4867aa..5a46e5ea 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2215,14 +2215,14 @@
 
 crbug.com/1067031 external/wpt/css/css-overflow/webkit-line-clamp-035.html [ Failure ]
 
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-margin-001.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-004.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-005.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-004.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-005.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-003.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-polygon-004.html [ Pass Failure ]
-crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000.html [ Pass Failure ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-margin-001.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-004.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-circle-005.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-004.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-ellipse-005.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-inset-003.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-polygon-004.html [ Failure Pass ]
+crbug.com/1339525 [ Win ] external/wpt/css/css-shapes/shape-outside/values/shape-outside-shape-arguments-000.html [ Failure Pass ]
 
 crbug.com/424365 external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-024.html [ Failure ]
 crbug.com/1129522 external/wpt/css/css-shapes/shape-outside/shape-image/gradients/shape-outside-linear-gradient-008.html [ Failure ]
diff --git a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
index cca4bdc..387f2f1 100644
--- a/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
+++ b/third_party/blink/web_tests/android/ChromeWPTOverrideExpectations
@@ -902,7 +902,6 @@
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/credentialless/image.https.window.html [ Crash Failure Pass ]
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/credentialless/link.https.window.html [ Crash Failure Pass ]
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/credentialless/redirect.window.html [ Failure Pass ]
-crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/credentialless/script.https.window.html [ Crash Failure Pass ]
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/credentialless/video.https.window.html [ Crash Timeout ]
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/reporting-navigation.https.html [ Failure Pass ]
 crbug.com/1050754 external/wpt/html/cross-origin-embedder-policy/reporting-subresource-corp.https.html [ Crash Failure ]
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version
index e109761..f6a9acd 100644
--- a/third_party/blink/web_tests/external/Version
+++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@
-Version: 2958c3d093920c58f2b8e73de8c5b8e4cadbc158
+Version: 4c05ce7850928490438c7e611b7df852a525a95e
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 f4231330..d1de99f 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
@@ -87092,6 +87092,19 @@
          ],
          {}
         ]
+       ],
+       "multiple-row-groups.tentative.html": [
+        "96e6173249c8d053c95f357161cee6b6f9fcf52c",
+        [
+         null,
+         [
+          [
+           "/css/reference/ref-filled-green-100px-square.xht",
+           "=="
+          ]
+         ],
+         {}
+        ]
        ]
       },
       "section-with-overflow-000.html": [
@@ -87224,6 +87237,19 @@
         {}
        ]
       ],
+      "table-border-006.html": [
+       "f0ebf25c08ef36b75da1b2770ba398c0ebfd478d",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "table-caption-and-cells-fixed-width.html": [
        "11984c3ea3f74e4506aaa41162451d2be72229b2",
        [
@@ -144036,6 +144062,45 @@
         ],
         {}
        ]
+      ],
+      "table-cell-multicol-nested-001.html": [
+       "5cb9eaf5643f5b485dd0ef3dbdc420a55fc43e6f",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "table-cell-multicol-nested-002.html": [
+       "b250841f92f958dcb4e21a2fd4e1f2ef8c4aab3b",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
+      "table-cell-multicol-nested-003.html": [
+       "f4e52910f1df994dd55ad8150c6551a5836ba64c",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
       ]
      },
      "with-custom-layout-on-same-element.https.html": [
@@ -144731,6 +144796,19 @@
        {}
       ]
      ],
+     "overflow-canvas.html": [
+      "e9529cb0bc81202c5689a507435ea088028a97fc",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-canvas-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "overflow-clip-cant-scroll.html": [
       "529ef1fad94432769428aad25ebcb27e28124d85",
       [
@@ -145124,6 +145202,19 @@
        {}
       ]
      ],
+     "overflow-video.html": [
+      "1721f8732be2be2711807c88c66cbb7b4dffdec8",
+      [
+       null,
+       [
+        [
+         "/css/css-overflow/overflow-video-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "scrollable-overflow-input-001.html": [
       "1b58803079f8b60b68eb1c57a0c522962e0a8019",
       [
@@ -241844,7 +241935,7 @@
       ]
      ],
      "layout-changes-on-percentage-based-timeline.html": [
-      "c69bee20ee8dbb6342bb7d988a6b99cb52d74992",
+      "c5a46a501e872fabfbd70526339e0c37a6b843c7",
       [
        null,
        [
@@ -245102,8 +245193,36 @@
       ]
      }
     },
+    "responsive": {
+     "toggle-animated-iframe-visibility.html": [
+      "f50ffaad34722afd3e626e6b41ccddf5f02ce0eb",
+      [
+       null,
+       [
+        [
+         "/web-animations/responsive/toggle-animated-iframe-visibility-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ]
+    },
     "timing-model": {
      "animations": {
+      "document-timeline-animation.html": [
+       "5fbfd2acfdd2f1961e8a966ad651ea31762407da",
+       [
+        null,
+        [
+         [
+          "/web-animations/timing-model/animations/document-timeline-animation-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "infinite-duration-animation.html": [
        "c641e5afa2aab390ebbc67df43af1bba34aa08a4",
        [
@@ -253473,12 +253592,12 @@
       []
      ],
      "fedcm-iframe.html": [
-      "0601971aeec13c8f81cd7647f449fb74c637aae9",
+      "546f66aa38106e0fb3a6d27849047ee47af12796",
       []
      ],
      "fedcm-manifest-not-in-list": {
       "fedcm.json": [
-       "9d919790050b4c0aaf8bd5a666ccf8a0ab40a40c",
+       "c044a7fd5eb8365d15ee29a2cec50856692b2c05",
        []
       ]
      },
@@ -253510,10 +253629,6 @@
       "0ec584d73d1f6d8626efe4c7190e5160fe527286",
       []
      ],
-     "revoke.py": [
-      "ed6fe00dfd7c3746c195ff2e0f782d9da31df032",
-      []
-     ],
      "set_cookie": [
       "8748426b548be3e262a18007ecb0b3a787e638ac",
       []
@@ -280488,6 +280603,10 @@
       "0d440ef20afa3d2456b702b2a1727a9f0717c4c1",
       []
      ],
+     "overflow-canvas-ref.html": [
+      "3ad440e371906b2fa4bc2ec4ae5c430267cf11c1",
+      []
+     ],
      "overflow-clip-cant-scroll-ref.html": [
       "d52fa0e9574cdbdb067106bccfd2014b9559b921",
       []
@@ -280576,6 +280695,10 @@
       "571ba348df4b2dfdd05b31d074496c95c340635d",
       []
      ],
+     "overflow-video-ref.html": [
+      "4a8a83e04a8c85faf429a8324b524111ec9d459c",
+      []
+     ],
      "reference": {
       "input-scrollable-region-001-ref.html": [
        "d7125ee2ef3285d461b2172208e23d8d4cc27a64",
@@ -299770,7 +299893,7 @@
      []
     ],
     "OWNERS": [
-     "9e3a2546556a896943d73233cb647edca73d9dd4",
+     "7f44d1b6e2ffff87a3e265b9ba62518534468d80",
      []
     ],
     "resources": {
@@ -332169,12 +332292,28 @@
       []
      ]
     },
+    "responsive": {
+     "resources": {
+      "block.html": [
+       "82840559690b3bb18bec0588db9d9eeb95e098e5",
+       []
+      ]
+     },
+     "toggle-animated-iframe-visibility-ref.html": [
+      "dab5bed7c81d2260766a78682f21be027f7c4575",
+      []
+     ]
+    },
     "testcommon.js": [
      "f5ea0a8f9ad24cf2919c8670394d1c9ca1f8db16",
      []
     ],
     "timing-model": {
      "animations": {
+      "document-timeline-animation-ref.html": [
+       "d1ee52a55302caa898b78a6af1bb392df1472616",
+       []
+      ],
       "infinite-duration-animation-ref.html": [
        "6b358bd4e7f3eb2e15d18246ec5722860a903a47",
        []
@@ -369896,14 +370035,7 @@
      ]
     ],
     "fedcm-network-requests.sub.https.html": [
-     "75b80afb383098ae1da1db5133fd15d9123f1c91",
-     [
-      null,
-      {}
-     ]
-    ],
-    "fedcm.https.html": [
-     "1bc3ebb90112ca79c3b716a24f32975f1c27fec9",
+     "a19cf6a4ac6eba8be96fd432ffa1d0bc7725706a",
      [
       null,
       {}
@@ -373323,7 +373455,7 @@
       ]
      ],
      "layer-scroll-timeline-override.html": [
-      "59b8590b5f19277acc719600c99136aef2e532ca",
+      "abdbed0685af724208d8e333ecfc7ac972ff08dc",
       [
        null,
        {}
@@ -374133,6 +374265,20 @@
         {}
        ]
       ],
+      "container-units-in-at-container-fallback.html": [
+       "3784499c387cc3f56356918064470461f039eada",
+       [
+        null,
+        {}
+       ]
+      ],
+      "container-units-in-at-container.html": [
+       "9ddca55ec15226dadba851a1b780cc258be7806d",
+       [
+        null,
+        {}
+       ]
+      ],
       "container-units-invalidation.html": [
        "0cb5b15f4a8e3666a5fbf60542e65fe6a5c31da8",
        [
@@ -460938,7 +461084,7 @@
        ]
       ],
       "script.https.window.js": [
-       "c3b4f0fa58c21637286b5c2f5ab6441ff466aebb",
+       "96bf7b08db88eff8fee5db18dc8486129ed52c48",
        [
         "html/cross-origin-embedder-policy/credentialless/script.https.window.html",
         {
@@ -518787,13 +518933,6 @@
        {}
       ]
      ],
-     "at-scroll-timeline-before-phase.html": [
-      "d2a978b230cb20f13d53ddd334e0f42c70decb8d",
-      [
-       null,
-       {}
-      ]
-     ],
      "at-scroll-timeline-cascade.html": [
       "9ba3a260c62a9671f1fd6cb6e4bcce8fa2ac7172",
       [
@@ -518808,13 +518947,6 @@
        {}
       ]
      ],
-     "at-scroll-timeline-element-offsets.html": [
-      "f0301cfa16c0d482e4a132e88318a496c3aa121a",
-      [
-       null,
-       {}
-      ]
-     ],
      "at-scroll-timeline-ignored.tentative.html": [
       "c2ad063002f8956a7d39307737b6512a45dd4653",
       [
@@ -518836,13 +518968,6 @@
        {}
       ]
      ],
-     "at-scroll-timeline-offset-invalidation.tentative.html": [
-      "13d816a062009742ab7db36026e115deb432734f",
-      [
-       null,
-       {}
-      ]
-     ],
      "at-scroll-timeline-orientation.html": [
       "fb13e8de54192b8bb47f073eba1abf96da982862",
       [
@@ -518958,7 +519083,7 @@
       ]
      ],
      "constructor.html": [
-      "0ba2f53cf929b74d5435308b459cebf1985e1a45",
+      "c5412566e982fdc9f448833bb4cb1bffc0f863cd",
       [
        null,
        {}
@@ -518979,14 +519104,7 @@
       ]
      ],
      "current-time-writing-modes.html": [
-      "ca66aa654e66ed418f201ff65dd08b561f6a98dd",
-      [
-       null,
-       {}
-      ]
-     ],
-     "current-time.html": [
-      "f011b40c13fd1bc3577f28c0442893d1576f278b",
+      "651d5fc48370f6acdf7d1fac824136d0ad7c27b9",
       [
        null,
        {}
@@ -518999,27 +519117,6 @@
        {}
       ]
      ],
-     "element-based-offset-clamp.html": [
-      "6aea82172384647a3519ccaffeb54d431df89461",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-based-offset-unresolved.html": [
-      "5b746d4c995eab8916788b02d4bcb6449772c174",
-      [
-       null,
-       {}
-      ]
-     ],
-     "element-based-offset.html": [
-      "7f18ce8e1da346e00c0bd590d53bb291cec8414b",
-      [
-       null,
-       {}
-      ]
-     ],
      "finish-animation.html": [
       "fd768651b490bafffc8bd75410e51b913ab8a914",
       [
@@ -519045,13 +519142,6 @@
        }
       ]
      ],
-     "multiple-scroll-offsets.html": [
-      "4a39548a996037d183ea9dc4259b4d8fe18af3c2",
-      [
-       null,
-       {}
-      ]
-     ],
      "pause-animation.html": [
       "9b263f843d267566c45830d8670fa909726df0c1",
       [
@@ -519074,7 +519164,7 @@
       ]
      ],
      "scroll-animation-effect-fill-modes.tentative.html": [
-      "e4e536ad7f543abcc8cf866d162f382948b2d31e",
+      "b9cc154676135656a06966f4c369acfa4f06903f",
       [
        null,
        {
@@ -552453,7 +552543,7 @@
       ]
      ],
      "h264-profile-levels.https.html": [
-      "7f0d3cdac6fad9559cc39b6999dc37f151f2194e",
+      "cb0b581c30b73d35f63775a1388b14a43112d169",
       [
        null,
        {
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/script.https.window.js b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/script.https.window.js
index c3b4f0f..96bf7b08 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/script.https.window.js
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-embedder-policy/credentialless/script.https.window.js
@@ -3,95 +3,97 @@
 // META: script=/common/dispatcher/dispatcher.js
 // META: script=./resources/common.js
 
-promise_test_parallel(async test => {
-  const same_origin = get_host_info().HTTPS_ORIGIN;
-  const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN;
-  const cookie_key = "coep_credentialless_script";
-  const cookie_same_origin = "same_origin";
-  const cookie_cross_origin = "cross_origin";
+window.onload = function() {
+  promise_test_parallel(async test => {
+    const same_origin = get_host_info().HTTPS_ORIGIN;
+    const cross_origin = get_host_info().HTTPS_REMOTE_ORIGIN;
+    const cookie_key = "coep_credentialless_script";
+    const cookie_same_origin = "same_origin";
+    const cookie_cross_origin = "cross_origin";
 
-  await Promise.all([
-    setCookie(same_origin, cookie_key, cookie_same_origin +
-      cookie_same_site_none),
-    setCookie(cross_origin, cookie_key, cookie_cross_origin +
-      cookie_same_site_none),
-  ]);
+    await Promise.all([
+      setCookie(same_origin, cookie_key, cookie_same_origin +
+        cookie_same_site_none),
+      setCookie(cross_origin, cookie_key, cookie_cross_origin +
+        cookie_same_site_none),
+    ]);
 
-  // One window with COEP:none. (control)
-  const w_control_token = token();
-  const w_control_url = same_origin + executor_path +
-    coep_none + `&uuid=${w_control_token}`
-  const w_control = window.open(w_control_url);
-  add_completion_callback(() => w_control.close());
+    // One window with COEP:none. (control)
+    const w_control_token = token();
+    const w_control_url = same_origin + executor_path +
+      coep_none + `&uuid=${w_control_token}`
+    const w_control = window.open(w_control_url);
+    add_completion_callback(() => w_control.close());
 
-  // One window with COEP:credentialless. (experiment)
-  const w_credentialless_token = token();
-  const w_credentialless_url = same_origin + executor_path +
-    coep_credentialless + `&uuid=${w_credentialless_token}`;
-  const w_credentialless = window.open(w_credentialless_url);
-  add_completion_callback(() => w_credentialless.close());
+    // One window with COEP:credentialless. (experiment)
+    const w_credentialless_token = token();
+    const w_credentialless_url = same_origin + executor_path +
+      coep_credentialless + `&uuid=${w_credentialless_token}`;
+    const w_credentialless = window.open(w_credentialless_url);
+    add_completion_callback(() => w_credentialless.close());
 
-  let scriptTest = function(
-    description, origin, mode,
-    expected_cookies_control,
-    expected_cookies_credentialless)
-  {
-    promise_test_parallel(async test => {
-      const token_1 = token();
-      const token_2 = token();
+    let scriptTest = function(
+      description, origin, mode,
+      expected_cookies_control,
+      expected_cookies_credentialless)
+    {
+      promise_test_parallel(async test => {
+        const token_1 = token();
+        const token_2 = token();
 
-      send(w_control_token, `
-        let script = document.createElement("script");
-        script.src = "${showRequestHeaders(origin, token_1)}";
-        ${mode};
-        document.body.appendChild(script);
-      `);
-      send(w_credentialless_token, `
-        let script = document.createElement("script");
-        script.src = "${showRequestHeaders(origin, token_2)}";
-        ${mode};
-        document.body.appendChild(script);
-      `);
+        send(w_control_token, `
+          let script = document.createElement("script");
+          script.src = "${showRequestHeaders(origin, token_1)}";
+          ${mode};
+          document.body.appendChild(script);
+        `);
+        send(w_credentialless_token, `
+          let script = document.createElement("script");
+          script.src = "${showRequestHeaders(origin, token_2)}";
+          ${mode};
+          document.body.appendChild(script);
+        `);
 
-      const headers_control = JSON.parse(await receive(token_1));
-      const headers_credentialless = JSON.parse(await receive(token_2));
+        const headers_control = JSON.parse(await receive(token_1));
+        const headers_credentialless = JSON.parse(await receive(token_2));
 
-      assert_equals(parseCookies(headers_control)[cookie_key],
-        expected_cookies_control,
-        "coep:none => ");
-      assert_equals(parseCookies(headers_credentialless)[cookie_key],
-        expected_cookies_credentialless,
-        "coep:credentialless => ");
-    }, `script ${description}`)
-  };
+        assert_equals(parseCookies(headers_control)[cookie_key],
+          expected_cookies_control,
+          "coep:none => ");
+        assert_equals(parseCookies(headers_credentialless)[cookie_key],
+          expected_cookies_credentialless,
+          "coep:credentialless => ");
+      }, `script ${description}`)
+    };
 
-  // Same-origin request always contains Cookies:
-  scriptTest("same-origin + undefined",
-    same_origin, '',
-    cookie_same_origin,
-    cookie_same_origin);
-  scriptTest("same-origin + anonymous",
-    same_origin, 'script.crossOrigin="anonymous"',
-    cookie_same_origin,
-    cookie_same_origin);
-  scriptTest("same-origin + use-credentials",
-    same_origin, 'script.crossOrigin="use-credentials"',
-    cookie_same_origin,
-    cookie_same_origin);
+    // Same-origin request always contains Cookies:
+    scriptTest("same-origin + undefined",
+      same_origin, '',
+      cookie_same_origin,
+      cookie_same_origin);
+    scriptTest("same-origin + anonymous",
+      same_origin, 'script.crossOrigin="anonymous"',
+      cookie_same_origin,
+      cookie_same_origin);
+    scriptTest("same-origin + use-credentials",
+      same_origin, 'script.crossOrigin="use-credentials"',
+      cookie_same_origin,
+      cookie_same_origin);
 
-  // Cross-origin request contains cookies in the following cases:
-  // - COEP:credentialless is not set.
-  // - script.crossOrigin is `use-credentials`.
-  scriptTest("cross-origin + undefined",
-    cross_origin, '',
-    cookie_cross_origin,
-    undefined);
-  scriptTest("cross-origin + anonymous",
-    cross_origin, 'script.crossOrigin="anonymous"',
-    undefined,
-    undefined);
-  scriptTest("cross-origin + use-credentials",
-    cross_origin, 'script.crossOrigin="use-credentials"',
-    cookie_cross_origin,
-    cookie_cross_origin);
-}, "Main");
+    // Cross-origin request contains cookies in the following cases:
+    // - COEP:credentialless is not set.
+    // - script.crossOrigin is `use-credentials`.
+    scriptTest("cross-origin + undefined",
+      cross_origin, '',
+      cookie_cross_origin,
+      undefined);
+    scriptTest("cross-origin + anonymous",
+      cross_origin, 'script.crossOrigin="anonymous"',
+      undefined,
+      undefined);
+    scriptTest("cross-origin + use-credentials",
+      cross_origin, 'script.crossOrigin="use-credentials"',
+      cookie_cross_origin,
+      cookie_cross_origin);
+  }, "Main");
+}
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/content-index.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/content-index.https.html
new file mode 100644
index 0000000..99af848
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/content-index.https.html
@@ -0,0 +1,150 @@
+<!DOCTYPE html>
+<title>Test Content Index API</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/utils.js"></script>
+
+<body>
+<script>
+const id = 'fenced-frame-id';
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  try {
+    await frame.execute(async (id) => {
+      navigator.serviceWorker.register(
+        "empty-worker.js", { scope: location.href });
+      const registration = await navigator.serviceWorker.ready;
+      return registration.index.add({
+        id,
+        title: 'same title',
+        description: 'same description',
+        url: 'resources/'
+      });
+    }, [id]);
+    assert_unreached('index.add executed without error; want error');
+  } catch(e) {
+    assert_equals(e.message, "Failed to execute 'add' on 'ContentIndex': " +
+    "ContentIndex is not allowed in fenced frames.")
+  }
+}, 'index.add should fail inside a fenced frame');
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  try {
+    await frame.execute(async (id) => {
+      navigator.serviceWorker.register(
+        "empty-worker.js", { scope: location.href });
+      const registration = await navigator.serviceWorker.ready;
+      return registration.index.delete(id);
+    }, [id]);
+    assert_unreached('index.delete executed without error; want error');
+  } catch(e) {
+    assert_equals(e.message, "Failed to execute 'delete' on 'ContentIndex': " + "ContentIndex is not allowed in fenced frames.");
+  }
+}, 'index.delete should fail inside a fenced frame');
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  try {
+    await frame.execute(async () => {
+      navigator.serviceWorker.register(
+        "empty-worker.js", { scope: location.href });
+      const registration = await navigator.serviceWorker.ready;
+      return registration.index.getAll();
+    });
+    assert_unreached('index.getAll executed without error; want error');
+  } catch(e) {
+    assert_equals(e.message, "Failed to execute 'getAll' on 'ContentIndex': " + "ContentIndex is not allowed in fenced frames.");
+  }
+}, 'index.getAll should fail inside a fenced frame');
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  const message = await frame.execute(async () => {
+    const getController = () => {
+      if (navigator.serviceWorker.controller) {
+        return navigator.serviceWorker.controller;
+      }
+      return new Promise(resolve => {
+        navigator.serviceWorker.addEventListener('controllerchange', () => {
+          resolve(navigator.serviceWorker.controller);
+        });
+      });
+    };
+
+    navigator.serviceWorker.register(
+      "content-index-sw.js", { scope: location.href });
+    return new Promise(async resolve => {
+      const ctrl = await getController();
+      ctrl.postMessage('add');
+      navigator.serviceWorker.onmessage = e => {
+        resolve(e.data);
+      }
+    });
+  });
+  assert_equals(message, "Failed to execute 'add' on 'ContentIndex': " +
+    "ContentIndex is not allowed in fenced frames.");
+}, 'index.add should fail from the service worker inside a fenced frame');
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  const message = await frame.execute(async () => {
+    const getController = () => {
+      if (navigator.serviceWorker.controller) {
+        return navigator.serviceWorker.controller;
+      }
+      return new Promise(resolve => {
+        navigator.serviceWorker.addEventListener('controllerchange', () => {
+          resolve(navigator.serviceWorker.controller);
+        });
+      });
+    };
+
+    navigator.serviceWorker.register(
+      "content-index-sw.js", { scope: location.href });
+    return new Promise(async resolve => {
+      const ctrl = await getController();
+      ctrl.postMessage('delete');
+      navigator.serviceWorker.onmessage = e => {
+        resolve(e.data);
+      }
+    });
+  });
+  assert_equals(message, "Failed to execute 'delete' on 'ContentIndex': " +
+    "ContentIndex is not allowed in fenced frames.");
+}, 'index.delete should fail from the service worker inside a fenced frame');
+
+promise_test(async () => {
+  const frame = attachFencedFrameContext();
+  const message = await frame.execute(async () => {
+    const getController = () => {
+      if (navigator.serviceWorker.controller) {
+        return navigator.serviceWorker.controller;
+      }
+      return new Promise(resolve => {
+        navigator.serviceWorker.addEventListener('controllerchange', () => {
+          resolve(navigator.serviceWorker.controller);
+        });
+      });
+    };
+
+    navigator.serviceWorker.register(
+      "content-index-sw.js", { scope: location.href });
+    return new Promise(async resolve => {
+      const ctrl = await getController();
+      ctrl.postMessage('getAll');
+      navigator.serviceWorker.onmessage = e => {
+        resolve(e.data);
+      }
+    });
+  });
+  assert_equals(message, "Failed to execute 'getAll' on 'ContentIndex': " +
+    "ContentIndex is not allowed in fenced frames.");
+}, 'index.getAll should fail from the service worker inside a fenced frame');
+</script>
+</body>
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/content-index-sw.js b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/content-index-sw.js
new file mode 100644
index 0000000..c2759d9
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/resources/content-index-sw.js
@@ -0,0 +1,28 @@
+self.addEventListener('install', e => e.waitUntil(skipWaiting()));
+self.addEventListener('activate', e => e.waitUntil(clients.claim()));
+
+self.addEventListener('message', async event => {
+  const method = event.data;
+  const {index} = self.registration;
+  const id = 'fenced-frame-id-sw';
+
+  let promise;
+  if (method === 'add') {
+    promise = index.add({
+      id,
+      title: 'same title',
+      description: 'same description',
+      url: 'resources/'
+    });
+  } else if (method === 'delete') {
+    promise = index.delete(id);
+  } else if (method === 'getAll') {
+    promise = index.getAll();
+  } else {
+    promise = Promise.resolve();
+  }
+
+  const message = await promise.then(() => 'success').catch(e => e.message);
+
+  event.source.postMessage(message);
+});
diff --git a/tools/json_schema_compiler/feature_compiler.py b/tools/json_schema_compiler/feature_compiler.py
index c6b8ebf..3882abb 100644
--- a/tools/json_schema_compiler/feature_compiler.py
+++ b/tools/json_schema_compiler/feature_compiler.py
@@ -174,6 +174,7 @@
                 'content_script': 'Feature::CONTENT_SCRIPT_CONTEXT',
                 'lock_screen_extension':
                 'Feature::LOCK_SCREEN_EXTENSION_CONTEXT',
+                'offscreen_extension': 'Feature::OFFSCREEN_EXTENSION_CONTEXT',
                 'web_page': 'Feature::WEB_PAGE_CONTEXT',
                 'webui': 'Feature::WEBUI_CONTEXT',
                 'webui_untrusted': 'Feature::WEBUI_UNTRUSTED_CONTEXT',
diff --git a/tools/json_schema_compiler/test/features_generation_unittest.cc b/tools/json_schema_compiler/test/features_generation_unittest.cc
index 80de7391..f088475 100644
--- a/tools/json_schema_compiler/test/features_generation_unittest.cc
+++ b/tools/json_schema_compiler/test/features_generation_unittest.cc
@@ -218,7 +218,8 @@
     comparator.contexts = std::vector<Feature::Context>(
         {Feature::BLESSED_EXTENSION_CONTEXT, Feature::BLESSED_WEB_PAGE_CONTEXT,
          Feature::CONTENT_SCRIPT_CONTEXT,
-         Feature::LOCK_SCREEN_EXTENSION_CONTEXT, Feature::WEB_PAGE_CONTEXT,
+         Feature::LOCK_SCREEN_EXTENSION_CONTEXT,
+         Feature::OFFSCREEN_EXTENSION_CONTEXT, Feature::WEB_PAGE_CONTEXT,
          Feature::WEBUI_CONTEXT, Feature::WEBUI_UNTRUSTED_CONTEXT,
          Feature::UNBLESSED_EXTENSION_CONTEXT});
     comparator.extension_types = {Manifest::TYPE_EXTENSION,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index e082b06c..193e8bc3 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -99203,20 +99203,6 @@
   <int value="2" label="Error">Launching the Chrome process failed.</int>
 </enum>
 
-<enum name="WebAppLauncherUpdateResult">
-  <int value="0" label="Success"/>
-  <int value="1" label="Failed to create temp dir">
-    Failed to create temporary directory in launcher's web-app data directory.
-  </int>
-  <int value="2" label="Failed to replace launcher">
-    Failed to atomically replace launcher with a copy or hardlink of
-    chrome_pwa_launcher.exe.
-  </int>
-  <int value="3" label="Latest version path does not exist">
-    Failed to find chrome_pwa_launcher.exe at the expected path.
-  </int>
-</enum>
-
 <enum name="WebAppManifestUpdateResult">
   <int value="0" label="No app in scope"/>
   <int value="1" label="Updating throttled"/>
diff --git a/tools/metrics/histograms/metadata/bookmarks/histograms.xml b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
index f80a0d33..a6716e9 100644
--- a/tools/metrics/histograms/metadata/bookmarks/histograms.xml
+++ b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
@@ -700,6 +700,17 @@
   </summary>
 </histogram>
 
+<histogram name="Bookmarks.Times.OnProfileLoad.TimeSinceAdded" units="days"
+    expires_after="2023-06-08">
+  <owner>wylieb@chromium.org</owner>
+  <owner>chrome-collections@google.com</owner>
+  <component>UI&gt;Browser&gt;Bookmarks</component>
+  <summary>
+    Records the average number of days since each bookmark was added. Recorded
+    on profile load.
+  </summary>
+</histogram>
+
 <histogram name="Bookmarks.UsageCountPerProfileType" enum="BrowserProfileType"
     expires_after="2022-12-18">
   <owner>rhalavati@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
index 6e3f849..51cad30 100644
--- a/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/metadata/histogram_suffixes_list.xml
@@ -7367,12 +7367,6 @@
   <affected-histogram name="Permissions.Action"/>
   <affected-histogram name="Permissions.DSE.AutoPermissionRevertTransition"/>
   <affected-histogram name="Permissions.DSE.EffectiveSetting"/>
-  <affected-histogram
-      name="Permissions.DSE.InvalidAutoPermissionRevertTransition.BackedUpSetting"/>
-  <affected-histogram
-      name="Permissions.DSE.InvalidAutoPermissionRevertTransition.EffectiveSetting"/>
-  <affected-histogram
-      name="Permissions.DSE.InvalidAutoPermissionRevertTransition.EndStateSetting"/>
   <affected-histogram name="Permissions.MissingOSLevelPermission.Action"/>
   <affected-histogram name="Permissions.MissingOSLevelPermission.ShouldShow"/>
   <affected-histogram name="Permissions.Prompt.Accepted.Persisted"/>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 3b7c51c..67aa877e 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -342,6 +342,9 @@
 <histogram
     name="Permissions.DSE.InvalidAutoPermissionRevertTransition.BackedUpSetting"
     enum="ContentSetting" expires_after="2022-07-01">
+  <obsolete>
+    Removed in June 2022, since the data it provides is no longer relevant.
+  </obsolete>
   <owner>andypaicu@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -357,6 +360,9 @@
 <histogram
     name="Permissions.DSE.InvalidAutoPermissionRevertTransition.EffectiveSetting"
     enum="ContentSetting" expires_after="2022-07-01">
+  <obsolete>
+    Removed in June 2022, since the data it provides is no longer relevant.
+  </obsolete>
   <owner>andypaicu@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
@@ -371,6 +377,9 @@
 <histogram
     name="Permissions.DSE.InvalidAutoPermissionRevertTransition.EndStateSetting"
     enum="ContentSetting" expires_after="2022-07-01">
+  <obsolete>
+    Removed in June 2022, since the data it provides is no longer relevant.
+  </obsolete>
   <owner>andypaicu@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/quota/histograms.xml b/tools/metrics/histograms/metadata/quota/histograms.xml
index f100800..d8088fb 100644
--- a/tools/metrics/histograms/metadata/quota/histograms.xml
+++ b/tools/metrics/histograms/metadata/quota/histograms.xml
@@ -94,7 +94,7 @@
   </summary>
 </histogram>
 
-<histogram name="Quota.EvictedBucketPerHour" units="units"
+<histogram name="Quota.EvictedBucketsPerHour" units="buckets"
     expires_after="2022-12-10">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index 6df6e29b..798eb8f 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -592,16 +592,6 @@
   </summary>
 </histogram>
 
-<histogram name="WebApp.Launcher.UpdateResult"
-    enum="WebAppLauncherUpdateResult" expires_after="2022-07-01">
-  <owner>davidbienvenu@chromium.org</owner>
-  <owner>jessemckenna@google.com</owner>
-  <summary>
-    The result of updating a single Progressive Web App (PWA) launcher with the
-    latest version of chrome_pwa_launcher.exe. Windows-only.
-  </summary>
-</histogram>
-
 <histogram name="WebApp.Mover.Result" enum="WebAppMoverResult"
     expires_after="2022-04-24">
   <owner>dmurph@chromium.org</owner>
diff --git a/tools/perf/chrome-health-run-daily.sh b/tools/perf/chrome-health-run-daily.sh
index 6030c75..a9616bb6 100644
--- a/tools/perf/chrome-health-run-daily.sh
+++ b/tools/perf/chrome-health-run-daily.sh
@@ -3,12 +3,16 @@
 # found in the LICENSE file.
 #!/bin/sh
 
-releaseBranchNo=5005
-pinnedReleaseMinusOne=93c720db8323b3ec10d056025ab95c23a31997c9 #101.0.4951.41
-pinnedMain=6ee574c7eb5719153bbe0d1eff07fd0acbd864cc #refs/heads/main@{#966041}
+# BEFORE YOU RUN THIS - In your ~ directory, execute the following. Note - this is named health_chromium so that cd chr<tab> works.
+# mkdir health_chromium
+# cd health_chromium
+# fetch --nohooks chromium
 
-# NOTE: If you are doing active development in this branch, the rest of this script may not work (it will attempt to check out different branches)
-cd ~/chromium/src
+releaseBranchNo=5112 #M104
+pinnedReleaseMinusOne=a1711811edd74ff1cf2150f36ffa3b0dae40b17f #103.0.5060.53
+pinnedMain=6ff741d380a7bfe8aafa4d0e6a8e84c46ddb4d39 #refs/heads/main@{#1018088}
+
+cd ~/health_chromium/src
 git fetch
 
 # Current release branch
@@ -24,6 +28,6 @@
 headOfMain=`git whatchanged --grep="Updating trunk VERSION" --format="%H" -1 | head -n 1`
 
 # M vs. M-1
-~/depot_tools/pinpoint experiment-telemetry-start --base-commit=$pinnedReleaseMinusOne --exp-commit=$headOfRelease --presets-file ~/chromium/src/tools/perf/chrome-health-presets.yaml --preset=chrome_health_pgo --attempts=40
+~/depot_tools/pinpoint experiment-telemetry-start --base-commit=$pinnedReleaseMinusOne --exp-commit=$headOfRelease --presets-file ~/chromium/src/tools/perf/chrome-health-presets.yaml --preset=chrome_health --attempts=40
 # Main
 ~/depot_tools/pinpoint experiment-telemetry-start --base-commit=$pinnedMain --exp-commit=$headOfMain --presets-file ~/chromium/src/tools/perf/chrome-health-presets.yaml --preset=chrome_health_pgo --attempts=40
\ No newline at end of file
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 2129c70..cc2e28b 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,24 +5,24 @@
             "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux_arm64/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell"
         },
         "win": {
-            "hash": "adcf9f60e35908138ad440207ded004627ccf43a",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/2a59c7427cfd780bcb98dfad01772b44468edc7a/trace_processor_shell.exe"
+            "hash": "d4b020a1896fded5857415d183e96a266d4434af",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/4d2a825326de4078f54adf4035ba2eff9901a052/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": "e4b4daabc84baf394356d8106740708170ee514f",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/010e6c1867a689266316ad607725cfd8ed11d3f9/trace_processor_shell"
+            "hash": "efd922cba49c5532f536a3aaf4c53f317ea6b83a",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/mac/048f619e850f327e1e6a9786680bebe582e4279a/trace_processor_shell"
         },
         "mac_arm64": {
             "hash": "e1ad4861384b06d911a65f035317914b8cc975c6",
             "full_remote_path": "perfetto-luci-artifacts/v25.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "25e9a9272f3b9bbacc96a3ae6b57f93ea0566549",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/048f619e850f327e1e6a9786680bebe582e4279a/trace_processor_shell"
+            "hash": "3d285f5800b43cf3f082fabea5fa65b0224043a0",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/4d2a825326de4078f54adf4035ba2eff9901a052/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/polymer/html_to_wrapper.gni b/tools/polymer/html_to_wrapper.gni
index 6a902fe..374f4e0d 100644
--- a/tools/polymer/html_to_wrapper.gni
+++ b/tools/polymer/html_to_wrapper.gni
@@ -5,28 +5,44 @@
 template("html_to_wrapper") {
   action(target_name) {
     script = "//tools/polymer/html_to_wrapper.py"
-    forward_variables_from(invoker, [ "visibility" ])
+
+    forward_variables_from(invoker,
+                           [
+                             "deps",
+                             "public_deps",
+                             "visibility",
+                           ])
 
     inputs = []
     outputs = []
 
     wrapper_extension = ".ts"
 
+    in_folder = "."
+    if (defined(invoker.in_folder)) {
+      in_folder = invoker.in_folder
+    }
+
+    out_folder = target_gen_dir
+    if (defined(invoker.out_folder)) {
+      out_folder = invoker.out_folder
+    }
+
     foreach(html_file, invoker.in_files) {
       extension = get_path_info(html_file, "extension")
       assert(extension == "html")
 
       wrapper_file = get_path_info(html_file, "dir") + "/" +
                      get_path_info(html_file, "file") + wrapper_extension
-      inputs += [ html_file ]
-      outputs += [ "$target_gen_dir/" + wrapper_file ]
+      inputs += [ "$in_folder/" + html_file ]
+      outputs += [ "$out_folder/" + wrapper_file ]
     }
 
     args = [
              "--in_folder",
-             rebase_path(".", root_build_dir),
+             rebase_path(in_folder, root_build_dir),
              "--out_folder",
-             rebase_path(target_gen_dir, root_build_dir),
+             rebase_path(out_folder, root_build_dir),
              "--in_files",
            ] + invoker.in_files
 
diff --git a/ui/base/DEPS b/ui/base/DEPS
index d5f0903..2f9fa3ec 100644
--- a/ui/base/DEPS
+++ b/ui/base/DEPS
@@ -1,6 +1,8 @@
 include_rules = [
   "+chromeos/crosapi/cpp/crosapi_constants.h",
+  "+chromeos/crosapi/mojom/emoji_picker.mojom.h",
   "+chromeos/lacros/lacros_paths.h",
+  "+chromeos/lacros/lacros_service.h",
   "+components/vector_icons",
   "+components/version_info",
   "+media/media_buildflags.h",
diff --git a/ui/base/emoji/emoji_panel_helper_lacros.cc b/ui/base/emoji/emoji_panel_helper_lacros.cc
new file mode 100644
index 0000000..fc481a4
--- /dev/null
+++ b/ui/base/emoji/emoji_panel_helper_lacros.cc
@@ -0,0 +1,21 @@
+// 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 "ui/base/emoji/emoji_panel_helper.h"
+
+#include "chromeos/crosapi/mojom/emoji_picker.mojom.h"
+#include "chromeos/lacros/lacros_service.h"
+
+namespace ui {
+
+bool IsEmojiPanelSupported() {
+  return chromeos::LacrosService::Get()
+      ->IsAvailable<crosapi::mojom::EmojiPicker>();
+}
+
+void ShowEmojiPanel() {
+  auto* lacros_service = chromeos::LacrosService::Get();
+  if (lacros_service->IsAvailable<crosapi::mojom::EmojiPicker>())
+    lacros_service->GetRemote<crosapi::mojom::EmojiPicker>()->ShowEmojiPicker();
+}  // namespace ui
\ No newline at end of file
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc
index e4f43e9..820dd77 100644
--- a/ui/base/ime/win/tsf_text_store.cc
+++ b/ui/base/ime/win/tsf_text_store.cc
@@ -471,8 +471,8 @@
       LONG old_delta = (LONG)replace_text_range_.start() -
                        (LONG)replace_text_range_.end() + replace_text_size_;
       LONG new_delta = start_pos - end_pos + text_buffer_size;
-      replace_text_range_.set_start(
-          std::min((uint32_t)start_pos, replace_text_range_.start()));
+      replace_text_range_.set_start(std::min(static_cast<size_t>(start_pos),
+                                             replace_text_range_.start()));
       // New replacement text ends after previous replacement text. We need to
       // use the new end after adjusting with previous delta.
       if ((uint32_t)end_pos >=
diff --git a/ui/display/display_features.cc b/ui/display/display_features.cc
index 762239d5..da0c774 100644
--- a/ui/display/display_features.cc
+++ b/ui/display/display_features.cc
@@ -4,6 +4,7 @@
 
 #include "ui/display/display_features.h"
 
+#include "base/feature_list.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 
@@ -11,6 +12,15 @@
 namespace features {
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+
+// Enables the rounded corners for the internal display.
+const base::Feature kRoundedDisplay{"RoundedDisplay",
+                                    base::FEATURE_DISABLED_BY_DEFAULT};
+
+bool IsRoundedDisplayEnabled() {
+  return base::FeatureList::IsEnabled(kRoundedDisplay);
+}
+
 // Enables using HDR transfer function if the monitor says it supports it.
 const base::Feature kUseHDRTransferFunction {
   "UseHDRTransferFunction",
@@ -21,6 +31,7 @@
       base::FEATURE_ENABLED_BY_DEFAULT
 #endif
 };
+
 #endif
 
 // This features allows listing all display modes of external displays in the
diff --git a/ui/display/display_features.h b/ui/display/display_features.h
index 265f136..d0137b9 100644
--- a/ui/display/display_features.h
+++ b/ui/display/display_features.h
@@ -13,6 +13,10 @@
 namespace features {
 
 #if BUILDFLAG(IS_CHROMEOS_ASH)
+DISPLAY_EXPORT extern const base::Feature kRoundedDisplay;
+
+DISPLAY_EXPORT bool IsRoundedDisplayEnabled();
+
 DISPLAY_EXPORT extern const base::Feature kUseHDRTransferFunction;
 #endif
 
diff --git a/ui/gfx/ipc/gfx_param_traits.cc b/ui/gfx/ipc/gfx_param_traits.cc
index 0499ab3..3bdf655 100644
--- a/ui/gfx/ipc/gfx_param_traits.cc
+++ b/ui/gfx/ipc/gfx_param_traits.cc
@@ -9,6 +9,7 @@
 
 #include <string>
 
+#include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 #include "build/build_config.h"
 #include "ui/gfx/ipc/geometry/gfx_param_traits.h"
@@ -21,8 +22,8 @@
 namespace IPC {
 
 void ParamTraits<gfx::Range>::Write(base::Pickle* m, const gfx::Range& r) {
-  m->WriteUInt32(r.start());
-  m->WriteUInt32(r.end());
+  m->WriteUInt32(static_cast<uint32_t>(r.start()));
+  m->WriteUInt32(static_cast<uint32_t>(r.end()));
 }
 
 bool ParamTraits<gfx::Range>::Read(const base::Pickle* m,
@@ -37,7 +38,7 @@
 }
 
 void ParamTraits<gfx::Range>::Log(const gfx::Range& r, std::string* l) {
-  l->append(base::StringPrintf("(%d, %d)", r.start(), r.end()));
+  l->append(base::StringPrintf("(%" PRIuS ", %" PRIuS ")", r.start(), r.end()));
 }
 
 #if BUILDFLAG(IS_MAC)
diff --git a/ui/gfx/range/mojom/range_mojom_traits.h b/ui/gfx/range/mojom/range_mojom_traits.h
index 5db4501e..381f0091 100644
--- a/ui/gfx/range/mojom/range_mojom_traits.h
+++ b/ui/gfx/range/mojom/range_mojom_traits.h
@@ -13,8 +13,12 @@
 
 template <>
 struct StructTraits<gfx::mojom::RangeDataView, gfx::Range> {
-  static uint32_t start(const gfx::Range& r) { return r.start(); }
-  static uint32_t end(const gfx::Range& r) { return r.end(); }
+  static uint32_t start(const gfx::Range& r) {
+    return static_cast<uint32_t>(r.start());
+  }
+  static uint32_t end(const gfx::Range& r) {
+    return static_cast<uint32_t>(r.end());
+  }
   static bool Read(gfx::mojom::RangeDataView data, gfx::Range* out) {
     out->set_start(data.start());
     out->set_end(data.end());
diff --git a/ui/gfx/range/mojom/range_mojom_traits_unittest.cc b/ui/gfx/range/mojom/range_mojom_traits_unittest.cc
index ba49cb8..31392d66 100644
--- a/ui/gfx/range/mojom/range_mojom_traits_unittest.cc
+++ b/ui/gfx/range/mojom/range_mojom_traits_unittest.cc
@@ -46,14 +46,17 @@
 }  // namespace
 
 TEST_F(RangeStructTraitsTest, Range) {
-  const uint32_t start = 1234;
-  const uint32_t end = 5678;
+  const size_t start = 1234;
+  const size_t end = 5678;
   gfx::Range input(start, end);
   mojo::Remote<mojom::RangeTraitsTestService> remote = GetTraitsTestRemote();
   gfx::Range output;
   remote->EchoRange(input, &output);
   EXPECT_EQ(start, output.start());
   EXPECT_EQ(end, output.end());
+
+  remote->EchoRange(gfx::Range::InvalidRange(), &output);
+  EXPECT_FALSE(output.IsValid());
 }
 
 TEST_F(RangeStructTraitsTest, RangeF) {
diff --git a/ui/gfx/range/range.cc b/ui/gfx/range/range.cc
index 699040e7..e2a194b 100644
--- a/ui/gfx/range/range.cc
+++ b/ui/gfx/range/range.cc
@@ -6,12 +6,13 @@
 
 #include <inttypes.h>
 
+#include "base/format_macros.h"
 #include "base/strings/stringprintf.h"
 
 namespace gfx {
 
 std::string Range::ToString() const {
-  return base::StringPrintf("{%" PRIu32 ",%" PRIu32 "}", start(), end());
+  return base::StringPrintf("{%" PRIuS ",%" PRIuS "}", start(), end());
 }
 
 std::ostream& operator<<(std::ostream& os, const Range& range) {
diff --git a/ui/gfx/range/range.h b/ui/gfx/range/range.h
index b3708e4..c2aceb2 100644
--- a/ui/gfx/range/range.h
+++ b/ui/gfx/range/range.h
@@ -13,6 +13,7 @@
 #include <ostream>
 #include <string>
 
+#include "base/numerics/safe_conversions.h"
 #include "build/build_config.h"
 #include "ui/gfx/range/gfx_range_export.h"
 
@@ -37,10 +38,12 @@
   constexpr Range() : Range(0) {}
 
   // Initializes the range with a start and end.
-  constexpr Range(uint32_t start, uint32_t end) : start_(start), end_(end) {}
+  constexpr Range(size_t start, size_t end)
+      : start_(base::checked_cast<uint32_t>(start)),
+        end_(base::checked_cast<uint32_t>(end)) {}
 
   // Initializes the range with the same start and end positions.
-  constexpr explicit Range(uint32_t position) : Range(position, position) {}
+  constexpr explicit Range(size_t position) : Range(position, position) {}
 
   // Platform constructors.
 #if BUILDFLAG(IS_APPLE)
@@ -52,27 +55,28 @@
     return Range(std::numeric_limits<uint32_t>::max());
   }
 
-  // Checks if the range is valid through comparison to InvalidRange().
+  // Checks if the range is valid through comparison to InvalidRange().  If this
+  // is not valid, you must not call start()/end().
   constexpr bool IsValid() const { return *this != InvalidRange(); }
 
   // Getters and setters.
-  constexpr uint32_t start() const { return start_; }
-  void set_start(uint32_t start) { start_ = start; }
+  constexpr size_t start() const { return start_; }
+  void set_start(size_t start) { start_ = base::checked_cast<uint32_t>(start); }
 
-  constexpr uint32_t end() const { return end_; }
-  void set_end(uint32_t end) { end_ = end; }
+  constexpr size_t end() const { return end_; }
+  void set_end(size_t end) { end_ = base::checked_cast<uint32_t>(end); }
 
   // Returns the absolute value of the length.
-  constexpr uint32_t length() const { return GetMax() - GetMin(); }
+  constexpr size_t length() const { return GetMax() - GetMin(); }
 
   constexpr bool is_reversed() const { return start() > end(); }
   constexpr bool is_empty() const { return start() == end(); }
 
   // Returns the minimum and maximum values.
-  constexpr uint32_t GetMin() const {
+  constexpr size_t GetMin() const {
     return start() < end() ? start() : end();
   }
-  constexpr uint32_t GetMax() const {
+  constexpr size_t GetMax() const {
     return start() > end() ? start() : end();
   }
 
@@ -109,8 +113,8 @@
   // If they don't intersect, it returns an InvalidRange().
   // The returned range is always empty or forward (never reversed).
   constexpr Range Intersect(const Range& range) const {
-    const uint32_t min = std::max(GetMin(), range.GetMin());
-    const uint32_t max = std::min(GetMax(), range.GetMax());
+    const size_t min = std::max(GetMin(), range.GetMin());
+    const size_t max = std::min(GetMax(), range.GetMax());
     return (min < max || Contains(range) || range.Contains(*this))
                ? Range(min, max)
                : InvalidRange();
@@ -129,8 +133,7 @@
 
  private:
   // Note: we use uint32_t instead of size_t because this struct is sent over
-  // IPC which could span 32 & 64 bit processes. This is fine since text spans
-  // shouldn't exceed UINT32_MAX even on 64 bit builds.
+  // IPC which could span 32 & 64 bit processes.
   uint32_t start_;
   uint32_t end_;
 };
diff --git a/ui/gfx/range/range_mac.mm b/ui/gfx/range/range_mac.mm
index cc1aa1ee..6818cd5f 100644
--- a/ui/gfx/range/range_mac.mm
+++ b/ui/gfx/range/range_mac.mm
@@ -22,8 +22,6 @@
     *this = InvalidRange();
   } else {
     set_start(range.location);
-    // Don't overflow |end_|.
-    DCHECK_LE(range.length, std::numeric_limits<size_t>::max() - start());
     set_end(start() + range.length);
   }
   return *this;
diff --git a/ui/gfx/render_text.cc b/ui/gfx/render_text.cc
index 19ff00f3..9db4aaff7 100644
--- a/ui/gfx/render_text.cc
+++ b/ui/gfx/render_text.cc
@@ -784,7 +784,7 @@
 
 bool RenderText::SetSelection(const SelectionModel& model) {
   // Enforce valid selection model components.
-  uint32_t text_length = static_cast<uint32_t>(text().length());
+  size_t text_length = text().length();
   std::vector<Range> ranges = model.GetAllSelections();
   for (auto& range : ranges) {
     range = {std::min(range.start(), text_length),
@@ -810,7 +810,7 @@
 }
 
 bool RenderText::SelectRange(const Range& range, bool primary) {
-  uint32_t text_length = static_cast<uint32_t>(text().length());
+  size_t text_length = text().length();
   Range sel(std::min(range.start(), text_length),
             std::min(range.end(), text_length));
   // Allow selection bounds at valid indices amid multi-character graphemes.
@@ -1919,7 +1919,8 @@
 bool RenderText::RangeContainsCaret(const Range& range,
                                     size_t caret_pos,
                                     LogicalCursorDirection caret_affinity) {
-  // NB: exploits unsigned wraparound (WG14/N1124 section 6.2.5 paragraph 9).
+  if (caret_pos == 0 && caret_affinity == CURSOR_BACKWARD)
+    return false;
   size_t adjacent = (caret_affinity == CURSOR_BACKWARD) ?
       caret_pos - 1 : caret_pos + 1;
   return range.Contains(Range(caret_pos, adjacent));
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 09429ce..42d798e 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -679,8 +679,7 @@
     }
 
     const size_t valid_end_pos = std::max(
-        segment.char_range.start(),
-        static_cast<uint32_t>(FindValidBoundaryBefore(text_, end_pos)));
+        segment.char_range.start(), FindValidBoundaryBefore(text_, end_pos));
     if (end_pos != valid_end_pos) {
       end_pos = valid_end_pos;
       width = run.GetGlyphWidthForCharRange(
@@ -692,9 +691,8 @@
     // not separate surrogate pair or combining characters.
     // See RenderTextHarfBuzzTest.Multiline_MinWidth for an example.
     if (width == 0 && available_width_ == max_width_) {
-      end_pos = std::min(
-          segment.char_range.end(),
-          static_cast<uint32_t>(FindValidBoundaryAfter(text_, end_pos + 1)));
+      end_pos = std::min(segment.char_range.end(),
+                         FindValidBoundaryAfter(text_, end_pos + 1));
     }
 
     return end_pos;
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index a3cfd28..eff0595 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -511,12 +511,14 @@
       size_t logical_index = run_list->visual_to_logical(i);
       const internal::TextRunHarfBuzz& run = *run_list->runs()[logical_index];
       if (run.range.length() == 1) {
-        result.append(base::StringPrintf("[%d]", run.range.start()));
+        result.append(base::StringPrintf("[%" PRIuS "]", run.range.start()));
       } else if (run.font_params.is_rtl) {
-        result.append(base::StringPrintf("[%d<-%d]", run.range.end() - 1,
+        result.append(base::StringPrintf("[%" PRIuS "<-%" PRIuS "]",
+                                         run.range.end() - 1,
                                          run.range.start()));
       } else {
-        result.append(base::StringPrintf("[%d->%d]", run.range.start(),
+        result.append(base::StringPrintf("[%" PRIuS "->%" PRIuS "]",
+                                         run.range.start(),
                                          run.range.end() - 1));
       }
     }
diff --git a/ui/gfx/selection_model.cc b/ui/gfx/selection_model.cc
index a792731..98d557c2 100644
--- a/ui/gfx/selection_model.cc
+++ b/ui/gfx/selection_model.cc
@@ -66,7 +66,7 @@
   for (auto selection : secondary_selections()) {
     str += ",";
     if (selection.is_empty())
-      base::StringAppendF(&str, "%" PRIu32, selection.end());
+      base::StringAppendF(&str, "%" PRIuS, selection.end());
     else
       str += selection.ToString();
   }
diff --git a/ui/gtk/native_theme_gtk.cc b/ui/gtk/native_theme_gtk.cc
index 779fbe2f..93281b8 100644
--- a/ui/gtk/native_theme_gtk.cc
+++ b/ui/gtk/native_theme_gtk.cc
@@ -213,86 +213,6 @@
   NotifyOnNativeThemeUpdated();
 }
 
-void NativeThemeGtk::PaintArrowButton(
-    cc::PaintCanvas* canvas,
-    const gfx::Rect& rect,
-    Part direction,
-    State state,
-    ColorScheme color_scheme,
-    const ScrollbarArrowExtraParams& arrow) const {
-  // Add the "flat" styleclass to avoid drawing a border.
-  auto context = GetStyleContextFromCss(
-      GtkCheckVersion(3, 20)
-          ? StrCat({GtkCssMenuScrollbar(), " #range GtkButton#button.flat"})
-          : "GtkRange.scrollbar.button.flat");
-  // Remove any rounded corners since arrow scrollbar buttons are tiny.
-  ApplyCssToContext(context, "* { border-radius: 0px; }");
-  GtkStateFlags state_flags = StateToStateFlags(state);
-  gtk_style_context_set_state(context, state_flags);
-
-  switch (direction) {
-    case kScrollbarUpArrow:
-      gtk_style_context_add_class(context, "top");
-      break;
-    case kScrollbarRightArrow:
-      gtk_style_context_add_class(context, "right");
-      break;
-    case kScrollbarDownArrow:
-      gtk_style_context_add_class(context, "bottom");
-      break;
-    case kScrollbarLeftArrow:
-      gtk_style_context_add_class(context, "left");
-      break;
-    default:
-      NOTREACHED();
-  }
-
-  PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, false);
-  PaintArrow(canvas, rect, direction, GtkStyleContextGetColor(context));
-}
-
-void NativeThemeGtk::PaintScrollbarTrack(
-    cc::PaintCanvas* canvas,
-    Part part,
-    State state,
-    const ScrollbarTrackExtraParams& extra_params,
-    const gfx::Rect& rect,
-    ColorScheme color_scheme) const {
-  PaintWidget(
-      canvas, rect,
-      GetStyleContextFromCss(GtkCheckVersion(3, 20)
-                                 ? StrCat({GtkCssMenuScrollbar(), " #trough"})
-                                 : "GtkScrollbar.scrollbar.trough"),
-      BG_RENDER_NORMAL, true);
-}
-
-void NativeThemeGtk::PaintScrollbarThumb(
-    cc::PaintCanvas* canvas,
-    const ui::ColorProvider* color_provider,
-    Part part,
-    State state,
-    const gfx::Rect& rect,
-    NativeTheme::ScrollbarOverlayColorTheme theme,
-    ColorScheme color_scheme) const {
-  auto context = GetStyleContextFromCss(
-      GtkCheckVersion(3, 20)
-          ? StrCat({GtkCssMenuScrollbar(), " #trough #slider"})
-          : "GtkScrollbar.scrollbar.slider");
-  gtk_style_context_set_state(context, StateToStateFlags(state));
-  PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true);
-}
-
-void NativeThemeGtk::PaintScrollbarCorner(cc::PaintCanvas* canvas,
-                                          State state,
-                                          const gfx::Rect& rect,
-                                          ColorScheme color_scheme) const {
-  auto context = GetStyleContextFromCss(
-      GtkCheckVersion(3, 19, 2)
-          ? "GtkScrolledWindow#scrolledwindow #junction"
-          : "GtkScrolledWindow.scrolledwindow.scrollbars-junction");
-  PaintWidget(canvas, rect, context, BG_RENDER_NORMAL, true);
-}
-
 void NativeThemeGtk::PaintMenuPopupBackground(
     cc::PaintCanvas* canvas,
     const ui::ColorProvider* color_provider,
diff --git a/ui/gtk/native_theme_gtk.h b/ui/gtk/native_theme_gtk.h
index f8444e1..5307f6c 100644
--- a/ui/gtk/native_theme_gtk.h
+++ b/ui/gtk/native_theme_gtk.h
@@ -29,29 +29,6 @@
   NativeThemeGtk& operator=(const NativeThemeGtk&) = delete;
 
   // ui::NativeThemeBase:
-  void PaintArrowButton(cc::PaintCanvas* canvas,
-                        const gfx::Rect& rect,
-                        Part direction,
-                        State state,
-                        ColorScheme color_scheme,
-                        const ScrollbarArrowExtraParams& arrow) const override;
-  void PaintScrollbarTrack(cc::PaintCanvas* canvas,
-                           Part part,
-                           State state,
-                           const ScrollbarTrackExtraParams& extra_params,
-                           const gfx::Rect& rect,
-                           ColorScheme color_scheme) const override;
-  void PaintScrollbarThumb(cc::PaintCanvas* canvas,
-                           const ui::ColorProvider* color_provider,
-                           Part part,
-                           State state,
-                           const gfx::Rect& rect,
-                           NativeTheme::ScrollbarOverlayColorTheme theme,
-                           ColorScheme color_scheme) const override;
-  void PaintScrollbarCorner(cc::PaintCanvas* canvas,
-                            State state,
-                            const gfx::Rect& rect,
-                            ColorScheme color_scheme) const override;
   void PaintMenuPopupBackground(
       cc::PaintCanvas* canvas,
       const ui::ColorProvider* color_provider,
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index e12cc34..c132e64 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -574,7 +574,7 @@
 }
 
 NSString* BridgedNativeWidgetTest::GetActualText() {
-  return GetViewStringForRange(ns_view_, NSMakeRange(0, NSUIntegerMax));
+  return GetViewStringForRange(ns_view_, EmptyRange());
 }
 
 NSString* BridgedNativeWidgetTest::GetActualSelectedText() {
@@ -582,7 +582,7 @@
 }
 
 NSString* BridgedNativeWidgetTest::GetExpectedText() {
-  return GetViewStringForRange(dummy_text_view_, NSMakeRange(0, NSUIntegerMax));
+  return GetViewStringForRange(dummy_text_view_, EmptyRange());
 }
 
 NSString* BridgedNativeWidgetTest::GetExpectedSelectedText() {
diff --git a/ui/views/examples/multiline_example.cc b/ui/views/examples/multiline_example.cc
index 7d60c6c2..9e4e43f3 100644
--- a/ui/views/examples/multiline_example.cc
+++ b/ui/views/examples/multiline_example.cc
@@ -33,7 +33,7 @@
 
 namespace {
 
-gfx::Range ClampRange(gfx::Range range, uint32_t max) {
+gfx::Range ClampRange(gfx::Range range, size_t max) {
   range.set_start(std::min(range.start(), max));
   range.set_end(std::min(range.end(), max));
   return range;
diff --git a/ui/views/style/platform_style.cc b/ui/views/style/platform_style.cc
index 59aa5bf..3a6e4df1 100644
--- a/ui/views/style/platform_style.cc
+++ b/ui/views/style/platform_style.cc
@@ -17,7 +17,7 @@
 #include "ui/views/controls/focusable_border.h"
 #include "ui/views/controls/scrollbar/scroll_bar_views.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
 #endif
 
@@ -60,7 +60,7 @@
 
 // static
 std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
-#if BUILDFLAG(IS_CHROMEOS)
+#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
   return std::make_unique<OverlayScrollBar>(is_horizontal);
 #else
   return std::make_unique<ScrollBarViews>(is_horizontal);